const与constexpr
Published on
const
C++11之前就存在const关键字,用于进行常量相关操作。它的主要用法如下:
// 定义常量,使其不能修改
const int value = 5;
// 可以使用常量定义数组
char arr[value];
char s[10];
// 指针不可修改,指向的内容可修改
char *const ptr1 = s;
// 指针可修改,指向的内容不可修改
const char *ptr2;
// 指针与指向的内容均不可修改
const char *const ptr3 = "string";
// 修饰函数参数,使其不可修改,如果同时使用引用可避免复制对象
void func(const A &a);
// 修饰成员变量,使其不能修改,只能进行初始化
class A
{
const int value = 5;
};
class B
{
const int value;
B(int v) : value(v) {}
};
// 修饰成员函数,使其不能修改成员变量
class C
{
public:
void func() const {}
};
// 修饰对象,使其只能调用const成员函数
const C c;
c.func();
constexpr
C++11引入关键字constexpr用于定义常量表达式,常量表达式的值在编译期间即可被计算出来。constexpr不仅可修饰变量,也可修饰函数与构造函数/析构函数等。
constexpr变量
const变量与constexpr变量之间的主要区别是,const变量的初始化可以推迟到运行时进行,而constexpr变量必须在编译时进行初始化。所有的constexpr变量都是const。
// 正确
constexpr float x = 42.0;
constexpr float y{108};
constexpr float z = exp(5, 3);
// 错误,未初始化
constexpr int i;
// 错误,j不是常量表达式
int j = 0;
constexpr int k = j + 1;
constexpr函数
在需要时,constexpr函数的返回值可在编译期间计算,并可用来初始化其它constexpr变量。如果不需要在编译期间计算,则constexpr函数与普通函数一样,在运行期间执行。
// 可在constexpr函数中使用递归
constexpr int factorial(int n)
{
return n <= 1 ? 1 : (n * factorial(n - 1));
}
自定义类型的字面值
// 实现具有constexpr构造函数的自定义类型
class Foo
{
public:
constexpr explicit Foo(int i) : _i(i) {}
constexpr int GetValue() const
{
return _i;
}
private:
int _i;
};
// 声明自定义类型的字面值
constexpr Foo foo(5);
constexpr if
从C++17开始,可以使用if constexpr语句,这将根据其后的条件在编译期间确定一条分支,并舍弃另一条分支。
template <typename T>
auto get_value(T t)
{
if constexpr (std::is_pointer_v<T>)
return *t;
else
return t;
}