c++ 关键字 const 的用法小结...
时间:2010-08-17 来源:dreamlins
1、消除C语言中预处理器的值替代产生的问题
C 语言中预处理器用值替代名字的用法是: #define FULLPATHNAME 255
这种方法避免了魔数(magic value)但存在类型问题。
应该完全用const来取代define的值替代。如:const int FULLPATHNAME = 255;
2、限定变量,提高安全性
例: const int n = 100;
这里的变量n在生存期内值不能改变。如果试图改变n的值,将引起编译错误。
3、const 用于集合时,变量值在编译时不能使用
例: const index = {1, 2, 3};
int array[index[2]]; //错误。index存放在内存中,编译时无法使用。
4、指向 const 的指针
在C++中,对于复杂的定义,是从标识符的开始处读它并从里向外读。
例: const int* x;
读作:x 是一个指针,它指向一个const int,表明指针所指的东西是不能被改变的。
也可以写做:int const* x;
表示:x 是一个指向恰好是 const 的 int 普通指针。
5、const 指针
要使指针本身成为一个 const 指针,必须把 const 标明的部分放在 * 的右边。
例如: int d=1; int* const x = &d;
此时指针本身在指针寿命期内不变,但其指向的值可以改变,如 *x = 2;
再如:int d=1;
const int* const x=&d; // (1)
int const* const x2=&d; // (2)
此时,指针和对象都不能改变。
6、不能把一个 const 对象的地址赋给一个非 const 指针,因为这样做可能通过被赋值指针改变这个 const 对象。
7、const 修饰函数参数和返回值
如果以值传递对象时,对用户来讲,用 const 限定没有意义(它意味着传递的参数在函数里是不能被修改的)。
如果以常量返回用户定义类型的一个对象的值,这意味着返回值不能被修改。
如果传递并返回地址, const 将保证该地址内容不会被改变。
A、传递 const 值
如果函数是以值传递的,可用 const 限定函数参数.
例: void f(const int i)
{
i++; //compile error.
}
在函数里,const 有这样的意义:参数不能被改变。所以它其实是函数创建者的工具,而不是函数调用者的工具。
为了不使调用者混淆,在函数内部用 const 限定参数优于在参数表里用 const 限定参数。
例: void f(int ic)
{
const int& i = ic;
i++; //compile error.
}
B、返回 const 值
对于内部数据类型来说,返回值是否是常量并没有关系,所以返回一个内部数据类型的值时,应该去掉 const 从而使用户程序员不混淆。
处理用户定义的类型时,返回值为常量是很重要的。如果一个函数返回一个类对象的值,其值是常量,那么这个函数的返回值不能是一个左值(即它不能被赋值,也不能被修改)
C、传递和返回地址
在C++中,如果不需要改变地址所指的内容,推荐通过常量(const)引用来传递参数,效果与值传递一样,但效率较高。
例: //Temporaries are constant
class X{};
X f() { return X(); } //Return by value
void g1(X&) {} //Pass by non-const reference
void g2(const X&) {} //Pass by const reference
main()
{
//Error: const temporary created by f():
//! g1(f());
//OK: g2 takes a const reference:
g2(f());
}
函数 f() 返回类 X 的一个对象的值。这意味着立即取 f() 的返回值并把它传递给其他函数时(正如 g1() 和 g2() 函数的调用),建立了一个临时变量,那个临时变量是常量。这样,函数 g1() 中的调用是错误的,因为 g1() 不带一个常量(const)引用,但是函数 g2()中的调用是正确的。
8、const 用于类
程序员可能想在一个类里建立一个局部常量,将它用在常数表达式里,这个常数表达式在编译期间被求值。然而, const 的意思在类里是不同的,所以必须使用另一技术—枚举,以达到同样的效果。我们还可以建立一个类对象常量(const)(正如我们刚刚看到的,编译器总是建立临时类对象常量)。但是,要保持类对象为常量却比较复杂。编译器能保证一个内部数据类型为常量,但不能控制一个类中错综复杂的事物。为了保证一个类对象为常量,引进了 const 成员函数:对于一个常量对象,只能调用 const 成员函数。
A、类里的const
const 常量在每个类对象里分配存储并代表一个值,这个值一旦被初始化以后就不能改变。在一个类里使用 const 的意思是“在这个对象寿命期内,这是一个常量”。然而,对这个常量来讲,每个不同的对象可以含一个不同的值。这样,在一个类里建立一个 const 时,不能给它初值。这个初始化工作必须发生在的任何代码执行之前,以防止在在构造函数主体的不同地方改变 const 的值。因此,可以在构造函数初始化表达式表中初始化。例:
class A
{
const size;
public:
A();
};
A::A(): size(200)
{
}
B、把一个内部数据类型封装在一个类里以保证用构造函数初始化有时可以大大地提高效率。
C、编译期间类中的常量。
编译器不能知道类中 const 常量的内容是什么,所以不能把它用作编译期间的常量。
作为替代,可以采用不带实例的无标记的 enum。
枚举不会占用对象中的存储空间,且在编译时被全部求值,它对类来说是局部的,但常数表达式能得到它的值。
例:
class A
{
const size = 100; // illegal
int array[size]; // illegal
}
class B
{
enum{ size = 100 }; // Ok
int array[size]; // Ok
}
当然可以采用静态常量static const实现编译期间求值。此外,应注意C++中枚举比C中有更严格的类型检查。