因为预处理只做文本替代,它既没有类型检查思想,也没有类型检查工具,所以预处理器的值替代会产生一些微小的问题,这些问题在c++中可以通过使用const而避免。
const小结:
1,const的引入:
因为预处理只做文本替代,它既没有类型检查思想,也没有类型检查工具,所以预处理器的值替代会产生一些微小的问题,这些问题在c++中可以通过使用const而避免。
2,c++编译器通常并不为const分配空间,它把这个定义保存在符号表中。当const常量被使用时,编译的时候就进行常量折叠。有一些情况会强制编译器进行存储空间分配:
(1),使用extern
(2),需要取一个const的地址
3,const是默认内部连接的,可使用extern改变它。
4,用const定义的常量必须进行初始化,而且初始化必须在定义的地方。
5,const可以用于集合,但编译器不能把一个集合存放在他的符号表中,所以必须分配内存。此时,const意味着“不能改变的一块存储空间“。然而,其值在编译时不能使用,因为编译器在编译时不需要知道存储的内容。
6,在c中const的意思是“一个不能被改变的普通变量“,在c中它总是占用存储空间而且它的名字是全局符。
即: const bufsize = 100;
char buf[bufsize]; // 是不对的,因为bufsize占用存储的某个地方,c编译器不知道它在编译时的值。
7,const与指针
(1) const int* x; 等同于 int const * x;
注:x指向的数据为const,x本身不是
int* const x; x为const的,x指向的数据不是;
(2) 我们可以把一个非const对象的指针赋给一个const对象的指针;但不可以把一个const对象的指针赋给一个非const对象的指针
即: int d = 1;
const int* v = &d; // that's ok!
d++; // that's ok!
//! (*v)++; //illegal
const int e = 3;
//! int* w = &e; // illegal
8,const类型的函数参数和返回值
(1),用const限定的参数表示该参数在函数内是不可修改的.
(2),返回值为const,限定了该返回值不能用做左值
9,临时变量自动成为常量
10,为防止处理函数对const限定的值进行修改,所以定义将指向const对象的指针传给普通指针为不合法.
11:类里的const:
(1),在一个类里使用const的意思是"在这个对象寿命期内,这是一个常量",它在每个类对象里分配存储并代表一个值.
(2),对某个常量来讲,每个不同的对象可以含有一个不同的值.初始化工作必须发生在构造函数里.const的初始化必须发生在构造函数的任何代码之前,一般在构造函数初始化表达式表中进行.
(3),因为在类对象里进行存储空间的分配,编译器不知道const成员的内容是什么,所以不能把它用作编译期间的常量.即,如下是不合法的:
class bob {
const size = 100; //illegal
int array[size]; //illegal
};
在类里的const的意思是:“在这个特定对象的寿命期内,而不是整个的类来说,这个值是不变的。“
(3)如何建立一个可以用在常数表达式里的类常量?
使用不带实力的无标记的enum。
枚举的所有制必须在编译时建立,它对类来说是局部的,但常数表达式能得到它的值。使用枚举不会占用对象的存储空间。
例: class bunch {
enum { size = 1000 };
int i[size];
};
(4),const对象和成员函数:
const对象表示"该对象的数据成员在对象寿命期内不改变“。
如果声明一个成员函数为const函数,则等于告诉编译器可以为一个const对象调用该函数。
可以声明为const成元函数的函数必须不改变对象的任何成员,并且不调用任何非const成元函数
(5),按位const与按成员const
const成元函数如何改变类的成员:
(1),按位const:对象中的每个位是固定的,所以对象的每个位的映像从不改变。对应方法:强制转换const: ((y*)this)->j++;
(2),按成员const:虽然整个对象从概念上讲是不变的,但是某个成员可能改变。对应方法:mutable int j;
12,volatile变量:
为满足多任务处理的需要,引入volatile限定词,volatile告诉编译器不要对volatile限定的变量做任何假设;
const volatile + 对象:该对象不能被程序员改变,但可被外界改变。