目录
一、const限定符
默认情况下,const对象仅在文件内有效,如果需要在多个文件中使用该const对象,需要用extern来声明一下。
//test.h文件中
extern const int a;//指明a的存在
//test.cpp文件中
extern const int a = 1;//定义并初始化a为1
//此时所有的文件都可访问这个a
1.初始化
一旦我们对某个对象加上const来修饰的话,就不能再对其进行更改了,所以在使用const来修饰对象时应注意对变量进行初始化。
2.const 变量
被const修饰的变量成为常变量,不可被修改。
int i = 10;
const int j = i;//将i的值拷贝给j,与i是否被const修饰无关
const int n = 0;
const double m= 1.0;
n++;//错误的,n被const修饰后成为常变量,不可再被修改
m += 1;//错误的
i = n;
3.const 引用
我们将被const修饰过的引用称为对常量的引用,该引用不能被用作修改其所绑定的对象,但是可以通过其他的途径来改变引用对象的值。(如a未被const修饰,b是a的别名,所以可以通过修改a的值来改变b的值。)
int a = 10;
const int& b = a;
a++;//a未被const修饰,可以更改
b++;//错误的,常变量不能被修改
int& c = b;//错误的,const被丢弃
需要注意的是:非常量引用不能指向一个常量对象
临时量
double d = 1.0;
const int&n1 = d;
int&n2 = d;//不加const会报错
对于为什么不加const直接引用会报错,我们需要来看一下编译器是如何将double类型转变为一个int类型的。
const int tmp = d;//编译器会产生该临时量
const int& n1 = tmp;
为了将n1能绑定一个整型,需要将d的double转换成int类,但是我们不能直接的修改d的类型,所以编译器会产生上面的这份代码,让n1绑定一个临时量,而这个临时量又被const修饰,所以n1也需要被const修饰。
4.const 指针
const在修饰指针的时候会有两种情况:在*前面加const和在*后面加const。
在*后面加const表示指针是一个常量,该指针不能被修改。
在*前面加const表示指针指向的对象是一个常量,该对象不能被修改。
int a = 10;
int b = 20;
const int*p1 = &a;//指向常量的指针
int const* p3 = &a;//指向常量的指针
(*p1)++;//错误的,指向的是常量不能被修改
int* const p2 = &a;//常量指针
p2 = &b;//常量指针不能被修改
const int* const p3 = &a;//p3是指向 常量对象 的 常量指针
5.const 返回值
让返回值具有const属性,常见于返回的是指针或引用。
const string& get_longer(const string&s1,const string&s2)
{
return s1.length() > s2.length() ? s1 : s2;
}
const int* getptr()
{
int* p =(int*) 0xCC;
return p;
}
6.const 成员函数
在成员函数后加const使得成员变量不能被修改。
class Num
{
public:
int Sum()const
{
num1++;//错误的,const修饰成员函数使得成员变量不能被修改
return num1 + num2;
}
private:
int num1=1;
int num2=2;
};
二、顶层/底层const
底层const:像指针指向的对象是一个常量这样的,所指的对象不能被修改
顶层const:像常量指针这样的,指向的对象能被修改,但是指针不能被修改
int n = 10;
const int*p1 = &a;//底层const
int* const p2 = &a;//顶层const
const int a = 10;//a不能被修改,顶层const
const int* const b = &n;//第一个const是底层,第二个是顶层
const int& c = n;//c不能被修改,底层
三、constexpr
常量表达式是指值不会改变并且在编译过程就能得到计算结果的表达式。
const int a = 10;
int b = 10;//b是可变的,所以不是常量表达式
const int n=a+1;//常量表达式
const int c = get_num();//不能在编译的过程中获得结果,所以不是常量表达式
在C++11中允许将变量声明为constexpr类型,由编译器来判断是否是一个常量表达式。
constexpr int n=10;//常量表达式
constexpr int m=n+1;//常量表达式
constexpr int num=get_num();//编译器判断是否为常量表达式
在C++11中定义了一种特殊的constexpr函数,该函数应足够简单使得编译时就可获得其结果,这样就可以用constexpr来初始化constexpr变量了。从而使其成为一个常量表达式。
constexpr int get_num1()//constexpr修饰,使得其在编译时就产生结果
{
return 1;
}
需要注意的是:
1.在constexpr声明中如果定义了的是指针,那么该限定符只会对指针有效,与其所指的对象无关。即constexpr定义的对象为顶层const。
2.constexpr指针的初始值必须是nullptr、0或是储存于固定地址的对象。
const int* p1 = nullptr;//p1指向的对象不能被修改,
constexpr int* p2 = nullptr;//指针p2不能被修改,即常量指针