1 const
1.1 const的作用
const主要有两个作用:只读限制(一般用来声明函数参数)和常量限制(用于不可变恒值声明),主要区别在于是否具有确定数值。
const修饰指针变量时,可以放在type*之前或之后,const type* var 表示var所指向的值*var是不可变的, type* const var表示指针变量var是不可变的,即var不能重新指向其他变量。
void fun1(const int num) {
int arr[num]; //ERROR,num只读性参数不用用作常量,只在函数调用时才能确定具体值
const int num1 = 10;
int arr1[num1]; //OK, 具有确定值的常量可以直接使用
int val = 100;
int val1 = 1000;
const int* p1 = &val;
*p1 = 200; //ERROR, *p1是常量不能再修改
p1 = &val1; //OK,p1可以重指向
int* const p2 = &val;
*p2 = 200; //OK,p2指向值可以改变
p2 = &val1; //ERROR, p2不能重指向
}
1.2 const 和 #define的区别
#define是预处理命令,它所定义的字符串在C++中称为宏定义;const是一个关键字(keyword),用于使标识符(identifier)的值为常量。
(1)编译时的处理方式不同:
#define作用原理本质上就是预处理阶段在宏调用处进行字符替换处理,不做任何计算;
const声明的常量具有变量属性,在编译时和运行时使用。
(2)类型和安全检查不同
#define宏定义的字符串所代表的变量或函数,在预处理阶段不做任何类型安全检查;
const常量是有类型的,在编译阶段必须进行类型安全检查。
(3)存储方式不同
#define宏定义的变量是不分配内存的;
const定义的常量本质上仍然是变量,是需要分配内存的。
但是,const常量在使用或运行时时可以节省空间,避免不必要的内存分配。
(4)define宏可以定义函数,此时函数相当于c++中的内联函数,而const只能定义常量。
2 constexpr
所谓常量表达式,指的是由多个常量组成且在编译过程中就能直接获取计算结果的表达式。常量表达式的计算在编译阶段,这极大提高程序的执行效率,因为表达式只需要在编译阶段计算一次,节省了每次程序运行时都需要计算一次的时间。
2.1 constexpr修饰变量
在 C++11 中新增了 constexpr 关键字,以用来修饰常量表达式,但是在定义常量时,const 和 constexpr 是等价的,都可以在程序的编译阶段计算出结果。C++ 内置类型的数据可以直接用 constexpr 修饰,自定义类型( struct / class )的数据也能直接用 constexpr 修饰。在constexpr声明中如果定义了一个指针,限定符conxtexpr仅对指针有效,与指针所指的对象无关
struct Car
{
float price;
const char* name;
};
void fun_test() {
const int var_const = 1234; //常量表达式 YES
constexpr int var_constexpr = 1234; //常量表达式 YES
printf("var_const: %d\n", var_const);
printf("var_constexpr: %d\n", var_constexpr);
constexpr Car car{15000.0, "geely"}; //常量表达式 YES
car.price = 10000.0; //ERROR,不能修改常量
const int*p = nullptr; //p是一个指向整形常量的指针
constexpr int* q = nullptr; //q是一个指向整数的常量指针
}
2.2 constexpr修饰函数
constexpr修饰一般函数构成常量表达函数的条件有:函数的返回值必须是常量表达式;函数必须事先定义;在函数体中,除了using 指令、typedef 语句、 static_assert 断言、return 语句之外,不能出现非常量表达式之外的语句。
constexpr int fun_test_constexpr()
{
constexpr int a = 100;
constexpr int b = 10;
return a + b;
}
2.3 constexpr类构造函数
使用 constexpr 修饰一个类的构造函数可以用来生成常量对象,常量构造函数有一个要求:构造函数的函数体必须为空,并且必须采用初始化列表的方式为各个成员赋值。
class Student {
public:
constexpr Student(const char* p, int age) :name_(p), age_(age)
{
}
private:
const char* name_;
int age_;
};
int main()
{
constexpr struct Person p1("Ella", 39);
cout << "luffy's name: " << p1.name_ << ", age: " << p1.age_ << endl;
return 0;
}