1 头文件里的const
const默认为内部连接(internal linkage),仅在本文件内可见.
为了使const能够被外部文件所引用,必须明确把它定义成extern
extern const int x = 1;
这样是是对常量做定义,而不是声明.
声明是这样的 extern const int i; 表示在其它地方有定义一个常量i;
2 const的空间分配问题
1 通常c++编译器并不为const创建存储空间,将它的定义保存在符号表里,这个叫编译期间的常量(可以用来给数组定义大小)
2 当extern是定义的一部分时,(同1中一样, 是定义不是声明),意味着不同的编辑单元可以引用它,所以它必须有存储空间
3 当下文中有取常量的地址时,常量也要分配存储空间.但这不妨碍编译器知道它是常量,仍然可以用来定义数组的大小.
4 当const用于定义数组或者自定义类型时(书中用的是"聚合"aggregate这个词),编译器不会将一个聚合保存在符号表中,因此要分配存储空间,并且它不是一个编译期间的常量.
例如
const int i[] ={1,2,3,4};
float f[i[3]]; //Illegal
5 const在C语言中的意思是"一个不可改变的变量".在C语言中,const总是占有存储并且全局连接,因此不可以当作一个编译期间的常量,
例如 :在c语言中,如下代码是非法的
const int bufsize=100;
int buf[bufsize];
6 总结: C++是否为常量分配存储空间取决于如何使用.
如果仅仅只把一个名字用一个值代替(累似#define),就不分配存储空间,
如果取常量地址 常量是聚合类型 将常量定义成extern ,就需要分配存储空间.
只要不是聚合类型,就可以当作编译期间常量使用
3 const指针
指向const的指针 const int *a; int const *b; (const在*左边)
const指针 int *const c; (const在*右边)
指向const的const指针 const int * const a; 或者 int const * const a;
4 赋值和类型检查
不能将一个const对象的地址赋给非const指针
这个检查主要在赋值和函数参数为指针时 进行检查
这个规则有个例外:
char *cp = "howdy";
5 参数传递和返回值
1 传递const 值
函数内参数不可变
2 返回const值
返回值是内建类型时,const是无关紧要的,因为它总是一个值而不是一个变量, 建议去掉const
返回值是自定义类型时,表示返回值不可以做左值(不能被赋值,也不能被修改)
3 传递const指针
无论什么时候传递一个地址给一个函数,都应该尽可能地用const修饰它,如果不这样做,就不能以const指针参数的方式使用这个函数
4 返回const 指针
返回值是const int *(指向const的指针) 只能被const int *指针接收
返回值是const int * const(指向const的const指针) 能被const int * const 和const int *接收,都表示指向的目标不被改变
但不能做为左值
5 C++中出现的新情况: 临时变量的地址传给函数
一个总是const的临时变量,它的地址可以被传递给函数.(使用引用,不能使用指针)
记住 临时变量总是const
class X{};
X f(){return X();}
void g1(X &){}
void g2(const X&){}
int main()
{
g1(f()); //错误
g2(f()); //正确
}
为什么C语言中做不到呢? 因为参数是指针时,必须明确指明地址
6 类中的const变量
1 普通const成员变量总会被分配存储空间,并且不会在类声明中赋初值 ,初值必须在构造函数的初始化列表中赋值.
所以普通const成员函数不能做为编译时常量使用
2 static const成员变量 可以看作编译期间的常量,因为static标记的变量只初始化一次, static const变量在类定义中初始化
(回忆: 普通static变量是在类中声明,类外定义的)
3 enum hack
不带实例的enum
一个枚举在编译期间必须有值, 并且不会占用类的存储空间
class Bunch
{
enum{ size = 1000};
int buf[size];
};
4 const成员函数
1 const放在函数后面,代表该函数不会改变成员变量
2 声明函数和定义函数 都要加const 否则认为是两个不同函数
3 const对象只能调用const成员函数, const对象调用两个同名函数时 调用的是const函数
4 在const成员函数中要如何改变成员变量?
在成员变量前面加 mutable 代表该变量可以在const成员函数中进行修改
5 const violate
violate代表"在编译器认识的范围外,该值可能改变" ,因此编译器不能对该值做任何假定,每次都必须去该值所在的地址读取
const violate变量表示 程序员不可以修改,但外部的代理程序可能修改的变量.