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

最新在弄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,因此需要用到推导),则这个类型不适合移动而只能使用拷贝实现异常安全

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

时间: 2024-07-30 20:00:42

c++ 11学习笔记-- 常量表达式(constexpr)的相关文章

c++ 11学习笔记--Lambda 表达式(对比测试Lambda ,bind,Function Object)

所有c++ coder都应该为这个语法感到高兴,说的直白一点,Lambda 表达式就是函数对象的语法糖. 还是直接看对比栗子吧,抄袭的是msdn的官网 该示例使用 for_each 函数调用中嵌入的 lambda 向控制台打印 vector 对象中的每个元素是偶数还是奇数. 使用lambda #include <algorithm> #include <iostream> #include <vector> using namespace std; int main()

C++11学习笔记

C++11 1.long long新类型 2.列表初始化 int t=0; int t={0}; int t(0); int t{0}; 注意:如果我们使用列表初始化有丢失信息的风险,则编译器报错 long double ld=3.1415926536; int a{ld},b={ld};//错误 int c(ld),d=ld;//正确,会丢失数据 3.空指针nullptr int *p1=nullptr; int *p2=0; int *p3=NULL;//尽量避免 4.constexpr类型

Derby-10.11学习笔记汇总

鲁春利的工作笔记,谁说程序员不能有文艺范? Derby-10.11学习笔记(一)简单介绍 http://luchunli.blog.51cto.com/2368057/1716255 Derby-10.11学习笔记(二)脚本介绍 http://luchunli.blog.51cto.com/2368057/1716464 Derby-10.11学习笔记(三)

802.11 学习笔记

一.网络服务 802 . 11 总共提供 9 种服务: 分布式 ( distribution ) 接入点收到帧 , 就会使用分布式服务将真传送至目的地. 整合 ( integration ) 该服务由分布式系统提供,它让分布式系统得以链接至非 IEEE802.11 网络 关联( association ) 移动式工作站向接入点登记,分布式系统就可以依据登记信息推断哪个移动式工作站该使用哪个接入点.仅仅有关联之后才干进行身份验证.在身份验证完毕之前,接入点会丢弃来自工作站的全部数据. 又一次关联(

c++ 11学习笔记--智能指针

C++ 98的 std::auto_ptr已经被彻底遗弃了,取而代之的是unique_ptr.shared_ptr与weak_ptr.大部分时候我们自己手动申请内存方式内存都是没有问题的,问题是如果程序很大了之后,一个复杂的对象,多次拷贝的代价非常高,很多地方都会使用到,只存在一份拷贝显然是最好的,这个时候对象生命周期的管理就会很复杂,所以c++引入了智能指针. 任何事物都会有两面性. Shared_ptr 摘录于Effective C++, 3rd Edition, Item 17: 在 st

C++11学习笔记之三lamda表达式,std::function, std::bind

//lamda //first lamda [] {}; // second lamda []() //or no need () when paramater is null { std::cout << "second" << std::endl; }();// last add(), express will call this lamda func // 3 with return type auto kkk = []() { return 1; }()

Kafka-2.11学习笔记(三)JavaApi访问kafka

欢迎访问:鲁春利的工作笔记,学习是一种信仰,让时间考验坚持的力量. Kafka底层是基于Scala语言实现的,但是也提供了Java的API接口. Java实现的消息生产者 package com.lucl.kafka.simple; import java.util.Properties; import kafka.javaapi.producer.Producer; import kafka.producer.KeyedMessage; import kafka.producer.Produc

【C++11学习笔记】类型判断的type_traits学习

一.简单的type_traits 我理解的type_traits是利用C++模板特性和static.enum特性定义编译器常量,例如 //std::integral_constant源码 typelate<class T, T v> struct integral_constant { static const T value = v; typedef T value_type; typedef integral_constant<T, v> type; operator valu

linux0.11学习笔记(1)

发布软件包包含内容: bootimage.Z - 具有美国键盘代码的压缩启动映像文件: rootimage.Z - 以1200kB 压缩的根文件系统映像文件: linux-0.11.tar.Z- 内核源代码文件: as86.tar.Z - linux bruce evans'二进制执行文件: 是16 位的汇编程序和装入程序: INSTALL-0.11 - 更新过的安装信息文件. 不足之处:不包括有关进程等待队列.虚拟文件系统.TCP/IP网络等方面的一些当前非常重要的代码. 目录: Linux/