您的位置:首页 > 编程语言 > C语言/C++

c++ 11学习笔记-- 常量表达式(constexpr)

2014-07-21 01:25 344 查看
最新在弄android ndk相关的,惊奇的发现最新的ndk10的版本已经gcc4.9了,我印象中,gcc4.8就支持C++0x11,14的支持,gcc再次走到了llvm的前面,LLVM最新的版本3.4.2应该只支持c++ 11,如果是同样的c++代码我一直认为llvm的效率会明显强过gcc.

废话不多说,让我们开始学习c++ 11吧,说实话我之前一直都很抗拒c++新的语法,感觉太难接受了,现在看来不熟悉也不行了。

常量表达式(constexpr)

常量表达式机制是为了:

提供了更多的通用的值不发生变化的表达式

允许用户自定义的类型成为常量表达式

提供了一种保证在编译期完成初始化的方法(可以在编译时期执行某些函数调用)

基本语法:

1.修饰常量表达式

int var1 = 100;

const int const_var2 = 200;

const int const_var3 = var1;

constexpr int constexpr_var1 = 3 + const_var2 * 4; //成立

// constexpr int constexpr_var2 = 3 + var1 * 4; //错误

// constexpr int constexpr_var3 = 3 + const_var3 * 4; //错误

2.修饰函数

constexpr int Inc(int i) {

return i + 1;

}

constexpr int a = Inc(1); // 正确

constexpr int b = Inc(cin.get()); // 错误

constexpr int c = a * 2 + 1; // 正确,但是如果没有Inc(1),也是错误的。

constexpr修饰的值要有初始值,和const不同的是初始化的值可以一个表达式,但是这个表达式的值必须是在编译期间就能确定值的。

3.修饰类或者结构体

struct A {

constexpr A(int xx, int yy): x(xx), y(yy) {}

int x, y;

};

constexpr A aa(1, 2);

constexpr int ccc = aa.x;

enum {SIZE_X = aa.x, SIZE_Y = aa.y};//llvm报错

Reference to local variable 'aa' declared in enclosing function 'main'

如果把constexpr A aa(1, 2);写成全局的就Ok,但是某些编译器并不会报错,我个人认为这个llvm编译器不太合理的地方,如果紧紧是aa是一个局部变量就不允许,但是aa本身的值是在编译的时候就确认了的。

个人的理解就是constexpr扩展了常量的含义,从语法上支持更多的常量定义,对比宏又有更好的类型检测和安全性,更强的约束语法带来更好的代码优化。

无意中在csdn论坛上看见大神的一段短话,摘录下来,很值的体会

constexpr:不光是可以取代模板是某些常量的表达更简洁,其实一个决定性的作用是支持地址类常量。这恰好补上了模板缺失的部分。比如有一个字符串常量"abc",很自然的可以认为其中的元素也是常量地址,对一个有编译期内容的常量地址取值理论上可以在编译器确定结果,但实际上按旧语法却不能直接拿去做为常量使用而是当作变量。

union带构造函数、支持带用户定义构造函数的类作为其成员,本意是用来支持某种多型变量,比如根据某个标志决定一个这样的union当前是什么类型。滥用则会导致数据错误。

noexcept支持推导,而容器元素在支持右值引用的情况下这类推导是很重要的。右值引用可以减少深拷贝的需求,但是在某些情况下会破坏强异常安全保证。利用noexcept推导来决定一个复杂类型作为容器元素的时候到底适合用移动还是适合用普通的拷贝策略来保证强异常安全。比如一个类型如果不支持无异常的移动(自身或任一基类或者数据成员的移动构造函数不支持noexcept,因此需要用到推导),则这个类型不适合移动而只能使用拷贝实现异常安全
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: