const
const
修饰的变量,不能对其进行赋值操作const
对象的内存,对其进行修改int main(){
const int data = 10;
int *p = const_cast<int*>(&data);
*p = 20;
std::cout << data << std::endl; //10
std::cout << *(&data) << std::endl; //20
return 0;
}
const
对象,编译器会将其出现的位置以其值替换data
的内存对其进行修改,但输出data
还是10;但其内存中的值确实被修改了 int main(){
int val = 10;
const int data = val;
int *p = const_cast<int*>(&data);
*p = 20;
std::cout << data << std::endl; //20
std::cout << *(&data) << std::endl; //20
return 0;
}
data
并非以常量表达式初始化,其初始值不能在编译器获取,所以编译器不会对其进行优化处理const
对象,不应该以任何理由被修改,很可能因为编译器的优化,产生莫名其妙的bugconst
对象只在当前文件类有效extern
关键字/*file_1.cc*/
extern const int data = 10;
/*file_2.cc*/
extern int data;
int main(){
std::cout << data << std::endl; //10
return 0;
}
constexpr
constexpr
修饰的变量,其必须以常量表达式初始化,且其具有const
属性/*file_1.cc*/
int val = 10;
constexpr int data = val; //error 表达式必须含有常量值
/*file_2.cc*/
const int val = 10;
constexpr int data = val; //正确,编译器优化将val替换为10
/*file_3.cc*/
int num = 10;
const int val = num;
constexpr int data = val; //error val并非以常量表达式初始化,所以其不能作为常量表达式
constexpr
修饰指针变量时,其只能作为顶层const
,且不能直接放在标识符前;同样的,其初始值必须是编译期可确定int global = 10;
int main(){
static int static_val = 10;
//均正常编译
constexpr int *p_1 = &global;
constexpr int *p_2 = &static_val;
return 0;
}
被constexpr
修饰的函数,隐式被指定为inline
1
被constexpr
修饰的函数,只有当遵循以下两点时,其才能作为常量表达式使用
void
,只要不被当作常量表达式使用,就不会报错return
constexpr int func(int arg){
int tmp = arg*arg;
for(int i=0;i<5;i++)
tmp *= arg;
return tmp;
}
int main(){
constexpr int data = func(10);
std::cout << data; //10000000
return 0;
}
上面的情况,因为
func
比较简单,所以其被折叠,可以作为常量表达式
但在下面这种情况,就不行了;非常不讲武德
constexpr int func(int arg){
int ret = arg;
for(int i=0;i<10000;i++)
for(int j=0;j<1000;j++)
for(int k=0;k<100;k++)
for(int l=0;l<10;l++)
ret++;
return ret;
}
int main(){
constexpr int data = func(10); //error 评估操作次数超过上限
std::cout << data;
return 0;
}
且constexpr
中定义的变量,无论其类型,必须初始化;但这并不意味着constexpr
中的变量具有const
属性
这里就不上测试代码了,各位hxd自行实验
const
和constexpr
细节较多,本文只做简述inline
只表示告诉编译器此函数可以被优化,并非让编译器优化 ↩︎