1. const存在的意义
相当于C语言的宏定义。
定义一个常量,在所有需要使用这个常量的地方用字符代替数值,更容易理解其含义,当这个常量值不再适用时方便修改
变量值不可改变
可以警惕防止某些程序一不小心改变了不应该被改变的值
2. const变量
const变量一旦被创建就不能改变,所以const对象定义时必须初始化。
默认状态下,const对象仅在文件内有效,不同文件定义的同名const对象被认为是两个变量,如果想让多个文件的const对象保持一致,可以如下定义:
//在file_1.cpp中定义并初始化一个const对象:
extern const int bufsize=512;
//在file_1.h头文件中声明
extern const int bufsize;//声明,不用也不能初始化,别的地方使用bufsize只需要#include “file_1.h”
3. const参数
在函数的参数列表中单个参数前面加上“const”关键字,就把该参数变成了此函数的const参数。const类型的函数参数表示在函数体内部,该参数的数值不会被改变。
这里可能会有个疑问:const参数既然表示该参数的值在函数范围内不能被修改,那我们是否可以传入const指针类型的参数,不改变指针地址,只改变指针指向的内容呢。
下面就此疑问来做三个试验:
【实验一】:改变const 指针型参数所指向的内容
// 编写一个函数随机创建一个包含<size>个Date类型数据的数组
bool CreatePoints(const Date* darr, const int size){
if(size < 0) return false;
srand((int)time(0));
for(int i = 0; i < size; ++i){
darr[i].year = rand()%3000; //from 0 year to 2999 year
……
}
return true;
}
//在main函数中调用此函数创建十个Date型数据的数组
int main(int argc,char **argv){
const Date * arrDate = new Date[10];
CreatePoints(arrDate, 10);
return 0;
}
编译后发现,编译器报如下错误
[图片]
由此得出结论:对于const指针型参数,指针所指向的内容会被当做 read-only处理而不能修改。
【实验二】:改变const指针型参数本身的地址
bool CreatePoints(const Date* darr, const int size){
darr = NULL;
}
int main(int argc,char **argv){
const Date * arrDate = new Date[10];
CreatePoints(arrDate,10);
return 0;
}
实验结果:编译通过,正常运行。
【实验三】:不可改变地址的const指针
把以上实验的CreatePoints函数的指针参数改成,<类型名> * const <指针>的形式,然后再在函数体里试图改变指针自身的值。
bool CreatePoints(Date* const darr, const int size){
darr = NULL;
}
得到的结果是,编译报错:
【结论】:
对于上面三个实验的结果这里又要回到【const变量】的话题,
(1) const+普通非指针型变量,有两种写法,其含义一样都是表示不可改变值的常量:
//以下两种写法是等价的,都是int型变量a是常量read-only的意思
const int a;
int const a;
(2)const+指针型变量,有三种写法:
前两种语句表达的意思相同,都是(*p)不可变,即指针p所指向的内容为const不可变;第三种写法意思是指针p本身是常量const的,也就是说,指针p的值(内存地址)是不可变的,而指针所指向的内容是可以变的
const int *p;//指针p所指向的内容不可以改变
int const *p;//指针p所指向的内容不可以改变
int * const p; //指针p自身的值不可以改变
4. const成员函数
const成员函数的一般形式是在函数的参数列表()后和函数体{ }之前加 const 关键字,表示该函数中不会改变类中的数据:
class complex{
public:
double real() const { return re; }
};
在类外的全局函数中使用const会报错
const成员函数是C++独有的const用法,其只能在类的成员函数中使用,如果在全局函数中使用会报编译错:
例如下面的代码:
bool isconst() const{ return true;}
编译后报错:
漏写const的类成员函数可能会给使用者造成困扰
有些看似并无影响的类成员函数如果不加const是不是也可以呢?还是让代码来说话:
class complex{
public:
double real(){ return re; }
};
//调用
int main(){
complex c1(2,1);
cout << c1.real() << endl; //正常使用,没有问题
const complex c2(3.5);
cout << c2.real() << endl; //报错,编译器理解为一个常量类实例试图调用自身可能会改变成员数据的成员函数
}
编译后第二个cout处出错:
好的编码习惯:
最后值得注意的是:在编写函数代码时,首先应该考虑的就是是否可以使用const关键字:函数的参数是否将在函数体内被改变,不会改变就要加const显示标注;类内成员函数是否会改变类型中的数据,不会改变要加const显示标注该函数为const型成员函数。