博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
const与constexpr
阅读量:3590 次
发布时间:2019-05-20

本文共 3798 字,大约阅读时间需要 12 分钟。


constexpr是C++11新标准规定的规定的关键字。有时我们很难分辨一个初始值是不是常量表达式,当然可以定义一个 
const变量并把它的初始值设为我们认为的某个常量表达式,但在实际使用时,尽管要求如此却常常发现初始值并非常量 
表达式的情况。可以说,这时的对象的定义与使用根本就是两回事。

C++11新标准规定,允许将变量声明为constexpr类型让编译器来验证变量的值是否是一个常量表达式。 
声明为constexpr的变量一定是一个常量,而且必须用常量表达式初始化: 
constexpr int mf = 0; // 0 是常量表达式 
constexpr int limit = mf + 1; // mf + 1 是常量表达式 
constexpr int sz = size(); // 只有当 size() 是一个constexpr函数时才是一条正确的声明语句

constexpr函数要求所定义的函数足够简单以使得编译时就可以计算其结果

constexpr int Dec(int i){ return i-1; }        
1
2

关键字 constexpr 于 C++11 中引入并于 C++14 中得到改善。它表示常数表达式。与 const 相同,它可应用于变量,因此如果任何代码试图修改该值,均将引发编译器错误。与const 不同,constexpr 也可应用于函数和类构造函数。 constexpr 指示值或返回值是常数,并且如果可能,将在编译时计算值或返回值。

1constexpr 变量

constconstexpr 变量之间的主要区别在于:const 变量的初始化可以延迟到运行时,而constexpr 变量必须在编译时进行初始化。所有 constexpr 变量均为常量,因此必须使用常量表达式初始化。

constexpr float x = 42.0;constexpr float y{
108};constexpr float z = exp(5, 3);constexpr int i; // Error! Not initializedint j = 0;constexpr int k = j + 1; //Error! j not a constant expression
1
2
3
4
5
6

一般来说,如果你认定变量是一个常量表达式,那就把它声明成为constexpr类型。

2constexpr 函数

constexpr 函数是在使用需要它的代码时,可以在编译时计算其返回值的函数。当其参数为 constexpr 值并且在编译时使用代码需要返回值时(例如,初始化一个constexpr 变量或提供一个非类型模板参数),它会生成编译时常量。使用非constexpr 参数调用时,或编译时不需要其值时,它将与正则函数一样,在运行时生成一个值。

#include 
using namespace std;// Pass by value constexpr float exp(float x, int n){ return n == 0 ? 1 : n % 2 == 0 ? exp(x * x, n / 2) : exp(x * x, (n - 1) / 2) * x;};// Pass by referenceconstexpr float exp2(const float& x, const int& n){ return n == 0 ? 1 : n % 2 == 0 ? exp2(x * x, n / 2) : exp2(x * x, (n - 1) / 2) * x;};// Compile time computation of array lengthtemplate
constexpr int length(const T(&ary)[N]){ return N;}// Recursive constexpr functionconstexpr int fac(int n){ return n == 1 ? 1 : n*fac(n - 1);}// User-defined typeclass Foo{public: constexpr explicit Foo(int i) : _i(i) {} constexpr int GetValue() { return _i; }private: int _i;};int main(){ // foo is const: constexpr Foo foo(5); // foo = Foo(6); // Error! //Compile time: constexpr float x = exp(5, 3); // const float a = 2.0; // const int b = 2; // constexpr float xx = exp2(a, b); // Error! constexpr float xx = exp2(2.0, 2); constexpr float y{ exp(2, 5) }; constexpr int val = foo.GetValue(); constexpr int f5 = fac(5); const int nums[]{ 1, 2, 3, 4 }; const int nums2[length(nums) * 2]{ 1, 2, 3, 4, 5, 6, 7, 8 }; cout << "The value of foo is " << foo.GetValue() << endl;}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

3 constexpr和指针

还记得const与指针的规则吗?如果关键字const出现在星号左边,表示被指物是常量;如果出现在星号右边,表示指针本身是常量;如果出现在星号两边,表示被指物和指针两者都是常量。

const不同,在constexpr声明中如果定义了一个指针,限定符constexpr仅对指针有效,与指针所指对象无关

const int *p     = 0; // non-const pointer, const dataconstexpr int *q = 0; // const pointer, non-const data   
1
2

与其它常量指针类似,const指针既可以指向常量也可以指向一个非常量:

int j = 0;constexpr int i = 2;constexpr const int *p = &i; // const pointer, const dataconstexpr int *p1 = &j; // const pointer, non-const data   
1
2
3
4

constexpr还能用于修饰类的构造函数,即保证如果提供给该构造函数的参数都是constexpr,那么产生的对象中的所有成员都会是constexpr,该对象也就是constexpr对象了,可用于各种只能使用constexpr的场合。注意,constexpr构造函数必须有一个空的函数体,即所有成员变量的初始化都放到初始化列表中。

struct A {    constexpr A(int xx, int yy): x(xx), y(yy) {}    int x, y;}; constexpr A a(1, 2);enum {SIZE_X = a.x, SIZE_Y = a.y};

转载地址:http://lsown.baihongyu.com/

你可能感兴趣的文章
vue解决打包后文件过大的问题-使用压缩插件打包后压缩文件-compression-webpack-plugin
查看>>
爆料称字节跳动实习生删库
查看>>
无缝滚动lunbot
查看>>
如何将Map集合写入txt文件中
查看>>
springboot参数检验,Assert使用
查看>>
htonl函数原理
查看>>
MACOS的Python虚拟环境使用笔记
查看>>
MAC系统使用Matplotlib显示中文问题亲测有效
查看>>
JavaScript的类型转换笔记
查看>>
JavaScript闭包实现计数器
查看>>
JavaScript中this关键字
查看>>
JavaScript两种定时器的使用
查看>>
阿里云服务器配置Nginx访问不到问题
查看>>
MAC电脑使用jupyter notebook
查看>>
Windows上设置jupternotebook远程访问
查看>>
查找数组中指定值下标
查看>>
不用strcat进行连接
查看>>
排列组合Cnm,有参数有返回值
查看>>
嵌套数组中查找元素
查看>>
gets函数
查看>>