const volatile mutable constexpr
一、const
2. const在不同位置的作用
const int fun();
函数返回值为 const
int fun(const int arg);
参数arg在函数内不可修改
int fun() const;
函数为只读函数,这个函数不能访问所有this所能调用的内存,不能对类对象的数据成员(准确说是非静态数据成员)做任何改变
const和constexpr修饰指针
constexpr int x = 110;
int main()
{
const int* p1 = nullptr; //p1是一个指向常量的指针,指针本身是变量
constexpr int* p2 = nullptr; //p2是一个指向变量的常量指针,指针本身是常量
constexpr const int* p3 = nullptr; //p3是一个指向常量的常量指针
const int* const p4 = nullptr; //p4是一个指向常量的常量指针
p1 = &x; // 正确,x是常量
//*p1 = 2; // 错误
//p2 = &x; // 错误
*p2 = 2; // 正确
//p3 = &x; // 错误
//*p3 = 2; // 错误
//p4 = &x; // 错误
//*p4 = 2; // 错误
return 0;
}
3. 常量(即const)对象
可以调用const成员函数,不能调用非const修饰的函数,非const对象既可以调用const成员函数,也可以调用非const成员函数
点击查看代码
#include <iostream>
class A
{
public:
void Func1() const
{
std::cout << "func1\n";
}
void Func2()
{
std::cout << "func2\n";
}
const int Func3()
{
std::cout << "func3\n";
return 1;
}
void Func4(const int n)
{
std::cout << "func4\n";
}
};
int main()
{
const auto a1 = A();
auto a2 = A();
a1.Func1(); // 正确
//a1.Func2(); // 错误
//a1.Func3(); // 错误
//a1.Func4(0); // 错误
a2.Func1();
a2.Func2();
a2.Func3();
a2.Func4(0);
}
4. const用于重载
点击查看代码
#include <iostream>
int f1(char* x)
{
return 1;
}
int f1(const char* x)
{
return 2;
}
int main()
{
char s1[] = "aaa";
const char s2[] = "bbb";
std::cout << f1(s2) << std::endl;
return 0;
}
二、volatile
转载自:详解C/C++中volatile关键字
volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。
为了安全起见,只要是等待别的程序修改某个变量的话,就加上volatile关键字。
一般说来,volatile用在如下的几个地方:
-
中断服务程序中修改的供其它程序检测的变量需要加volatile;
-
多任务环境下各任务间共享的标志应该加volatile;
-
存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;
三、mutable
四、constexpr
const expression 常量表达式
c++11规定:允许将变量声明为constexpr类型,以便由编译器来验证变量的值是否是一个常量表达式。声明为constexpr的变量一定是一个常量,而且必须用常量表达式初始化。
一般来说,如果你认定变量是一个常量表达式,那就把它声明成constexpr类型。
constexpr int n1 = 20; //20是常量表达式
constexpr int n2 = n1 + 1; //n1+1是常量表达式
constexpr int n3 = size(); //只有当`size()`是一个constexpr函数时才是一条正确语句
五、const和constexpr的区别
const表示的是变量只读,注意是变量,constexpr表示的是常量,在编译期就能确定值
点击查看代码
#include <iostream>
using namespace std;
int main()
{
int a = 10;
const int & con_b = a;
cout << con_b << endl;
a = 20;
cout << con_b << endl; // 输出20,const修饰的con_b值被修改了
}
五、检查类型是否为const或volatile限定,添加、移除const或volatile限定
const int ic = 0;
volatile int iv = 0;
std::cout << std::is_const< decltype(ic)>::value;//1
std::cout << std::is_const<int>::value;//0
std::cout << std::is_const<const int*>::value;//0
std::cout << std::is_const<int* const>::value;//1
std::cout << std::is_volatile<decltype(iv)>::value;//1
std::cout << std::is_volatile<int>::value;// 0
std::is_const<const int>::value_type Bool;//Bool是一个没有初始化的bool型变量
std::is_const<const int>::type;
std::remove_const<const int>::type Int;//Int是一个没有初始化的int型变量
std::remove_cv<const volatile int>::type CV;//CV是一个没有初始化的int型变量
int i = 0;
auto&& ret1 = std::as_const<int>(i);//类型为const int&
auto&& ret2 = std::as_const(i);//类型为const int&
auto ret3 = std::as_const(i); //类型为int
std::add_const<int>::type CI = 0; //CI是一个const int型且初始值为0的常量(const必须初始化)