因为预处理只做文本替代,它既没有类型检查思想,也没有类型检查工具,所以预处理器的值替代会产生一些微小的问题,这些问题在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 + 对象:该对象不能被程序员改变,但可被外界改变。 |