1.定义.
const是C++中常用的类型修饰符,程序员可以使用关键字const来指定对象是不可修改的,即const修饰的类型为常类型.
2.const具体作用与效果.
const的主要作用有定义常量、修饰函数参数、修饰函数返回值、修饰函数的定义体、定义类中某个成员为常态函数(即不改变类中的数据成员).其中:
1)定义const常量.
①简单类型常量.
这种常量在定义时,修饰符const放置在类型说明符前后作用一样.如:
int const x=2;
const int x=2;
int const a[5]={1, 2, 3, 4, 5};
const int a[5]={1, 2, 3, 4, 5};
②对象常量,如:
<类名> const <对象名>
const <类名> <对象名>
2)方便类型安全检查.
与#define相比, const常量有数据类型,而宏常量没有数据类型.编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换中可能会产生意料不到的错误.在c++中使用const常量而不使用宏常量,即const常量完全取代宏常量.
3)防止参数被意外修改,提高程序的健壮性.
示例代码:
void test(const int x)
{
x=2;
}
即程序会报错: assignment of read-onlyparameter ‘x'.
4)节省空间,提高效率.
const定义给出的是对应的内存地址,而不是像#define一样给出的是立即数,即const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝.编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,即成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率很高.
3.const的使用方法.
1)const修饰指针.
使用const修饰指针时,因const的位置不同,而含意不同.如:
const int* a = & b [1]
int const *a = & b [2]
int* const a = & b [3]
const int* const a = &b [4]
[1]与[2]完全相同,*a 是数值常量,不可修改,但a指向的地址可以修改。[3]中a 是指针常量,不能更改指针指向的地址。[4]中a与*a都不可修改。
2)const修饰引用.
使用const修饰引用时,被说明的引用为常引用,该引用所引用的对象不能被更改.
const <类型说明符> & <引用名>
如:
const double & v;
注意:在实际应用中,常指针和常引用往往用来作函数的形参,这样的参数称为常参数.
3)const修饰函数参数.
①传递过来的参数在函数内不可以改变(无意义,因为x本身就是形参).
void f(const int x);
②参数指针所指内容为常量不可变.
void f(const char* x);
③参数指针本身为常量不可变(也无意义,因为char* x也是形参)
void f(char* const x);
④参数为引用,为了增加效率同时防止修改.
void f(const Class& x); //引用参数在函数内不可以改变
void f(const TYPE& x); //引用参数在函数内为常量不可变
4)const修饰函数返回值.
const intf1() //这个其实无意义,因为参数返回本身就是赋值.
const int*f2() //调用时 const int *p1 = f2(); 我们可以把f2()看作成一个常量,即指针内容不可变.
int* constf3() //调用时 int *const p1 = f3(); 我们可以把f3()看作成一个变量,但指针本身不可变.
注意:通常不建议用const修饰函数返回值类型为某个对象或对某个对象引用的情况.
5)const修饰成员变量.const修饰类的成员函数,表示成员常量不能被修改,同时它只能在初始化列表中赋值.
class Test
{
…
const int test; //成员常量不能被修改
…
Test(int x): test(x) { }; //只能在初始化列表中赋值
}
6)const修饰成员函数.
const修饰类的成员函数,则该成员函数不能修改类中任何非const成员函数.一般写在函数的最后来修饰.
示例代码:
class Test
{
// 函数后面加const表示函数不可以修改class的成员.换而言之,这种函数不能改变this实例的任何数据.
void f()const; //常成员函数,它不改变对象的成员变量.也不能调用类中任何非const成员函数.
}
对于const类对象/指针/引用,只能调用类的const成员函数,因此,const修饰成员函数的最重要作用就是限制对于const对象的使用.
7)const类对象/对象指针/对象引用.
const修饰类对象表示该对象为常量对象,其中的任何成员都不能被修改.对于对象指针和对象引用也是一样.const修饰的对象,该对象的任何非const成员函数都不能被调用,因为任何非const成员函数会有修改成员变量的企图.
示例代码:
class Test
{
void f1();
void f2() const;
}
const Test a;
a.f1(); 错误 // const 对象不能调用普通函数,必须调用const函数.
a.f2(); 正确
const Test* a =new Test();
a->f1(); 错误
a->f2(); 正确
4. const常量与#define宏定义的区别.
1) 编译器处理方式不同.
#define宏是在预处理阶段展开.
const常量是编译运行阶段使用.
2) 类型和安全检查不同.
#define宏没有类型,不做任何类型检查,仅仅是展开.
const常量有具体的类型,在编译阶段会执行类型检查.
3) 存储方式不同.
#define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存.
const常量会在内存中分配(可以是堆中也可以是栈中).