01、c++ primer 之 const

来源:互联网 发布:亲朋棋牌刷金币软件 编辑:程序博客网 时间:2024/06/04 19:54

最近在看c++ primer,记录下读书笔记。

const关键字

当我们希望使用一个变量时,同时又不希望被改变时候,就可以用const来定义一个变量。这个变量就变成不可变的变量,约等于一个常量。

const int buf_size = 512;buf_size = 512;//错误:试图向const对象写值
const对象一经初始化就不能被改变,所以const对象必须初始化。

const int k;//错误,k是一个未经初始化的变量

如果用一个对象去初始化另外一个对象,它们是不是const都无关紧要。

int i = 42;const int ci = i;int j = ci;
这种间接的拷贝赋值,只要把对象的值拷贝过去,原来的对象就和新的对象就没什么关系了。

由于const定义只在当前文件内有效,当我们想把它共享给多个文件,同时这个变量又不是一个常量表达式时,我们只需要在定义和声明时候加上关键字 extern就行了。

//file.c,在这个文件中定义并初始化一个常量extern const int buf_size = fun();//file.h头文件,这个buf_size和file.c中的是同一个extern const int buf_size;

const引用和普通的引用不同的是,当被绑定的那个const变量无法通过被绑定引用改变。也就是说const的引用无法改变。

const int ci = 1024;const int &r1 = ci;r1 = 42;//错误,r1是一个const引用int &r2 = ci;//错误,等号两边类型不同
这里很容易看出ci是一个常量,但是r2却是一个普通引用。因为不允许给ci赋值,所以通过别的途径给ci赋值也是非法的。


前面提到,引用的类型必须和其所引用对象的类型一致。但是这里有两个例外,第一种情况就是,在初始化常量引用时候允许用任意表达式作为初始值,只要该表达式能转换成引用的类型即可。

int i = 42;const int &r1 = i;const int &r2 = 42;const int &r3 = r1 * 2;
再来看一种错误的:

double dval = 3.14;const int &ri = dval;
这里是想用int类型去绑定一个double类型的dval,在编译器上就会转成下面这种形式

const int temp = dval;//生产一个临时的int变量const int &ri = temp;//让ri绑定这个temp
在编译器上,其实绑定的是一个临时变量,既然我们用了绑定,就是想通过ri去改变dval的值,但是绑定的却是一个临时变量。所以C++把这个视为非法操作。

const绑定的值可以不是const变量,所以我们虽然不能通过绑定去改变值,但是我们可以通过其他途径去改变。

int i = 42;const int &r1 = i;r1 = 50;//错误,试图通过r1改变ii = 50;//正确,i是一个普通变量。

指向常量的指针,是不允许通过指针去改变所指对象的值。要想存放常量对象的地址,就必须使用指向常量的指针。

const int i = 20;int *p1 = &i;//错误,p1是一个普通指针const int *p2 = &i;//正确p2是一个const的int指针*p2 = 30;//错误不能给*p2赋值

指向常量的指针或者引用,只不过是指针或者引用“自以为是”,罢了,他们以为自己指向常量,就不去修改他们的值,但是可以通过其他途径修改。

const指针,若是一个常量指针,那么在定义时候就必须被初始化,一旦初始化完成,那就指针指向的地址就不允许修改。

*放在const之前和之后是不同的

const int i = 50;const int *p1 = &i;//const放在*之前,表示p1指向的值不能改变int k = 30;int *const p2 = &k//const放在*之后表示,p2指向的地址不能改变

还有一种就是在*之前和之后都加const

const int a = 30;const int *const pa = &a;//表示pa是一个指向常量对象的常量指针

既不能通过pa改变a的值,也不能改变pa指向的地址。
这里还有两个概念就是顶层const(top-level-const)和底层const(low-level-const)。就同上面的一样,在左边的底层const,代表指针指向的值不能改变;在右边的是顶层const,表示指针指向的地址不能改变。

在当执行拷贝操作时候,顶层const还是底层const区别明显,顶层const并比影响什么。因为拷贝时候不会改变对象值的大小,只是简单是拷贝出拷贝入,所以顶层const不影响什么,是否是常量都没什么影响。

int i = 0;const int ci = 42;i = ci;//正确,顶层const,对ci的拷贝无影响const int *p2 = &ci;const int *const p3 = p2;p2 = p3;//正确,p2和p3具有相同的数据类型,而且有相同的底层const资格


但是底层const的限制要注意,拷入和拷出对象必须要有相同的底层const资格,两个对象的数据类型要和可以互相转换,非常量可以转换成常量,反之不行。

int *p = p3;//错误,没有相同的底层const资格p2 = &i;//正确,int * 可以转换成const int *
p3比较特殊及时顶层const也是底层const,所以在拷贝时候无需关系他是顶层const还是底层const,但是千万不要给p3赋值。







0 0
原创粉丝点击