一、C++ const 和 constexpr 的区别?

constexpr 表示这玩意儿在编译期就可以算出来(前提是为了算出它所依赖的东西也是在编译期可以算出来的)。

const 只保证了运行时不直接被修改(但这个东西仍然可能是个动态变量)。

constexpr 是 C++11 引入的,一方面是为了引入更多的编译时计算能力,另一方面也是解决 C++98 的 const 的双重语义问题。

const修饰的是类型,constexpr修饰的是用来算出值的那段代码。

在 C 里面,const 很明确只有「只读」一个语义,不会混淆。C++ 在此基础上增加了「常量」语义,也由 const 关键字来承担,引出来一些奇怪的问题。C++11 把「常量」语义拆出来,交给新引入的 constexpr 关键字。

二、为什么用 constexpr

预判错误

int i; // not constant
const int size = i; // fine! 可以,但为什么不在这里就先判断出问题的隐患呢? int arr[size]; // Error!

然而对于constexpr,则表明这个值不仅是constant的,而且也是编译期确定的

int i; // not constant
constexpr int size = i; // Error!

于是,constexpr修饰的变量是可以表示数组大小的。

数组初始化

constexpr可以用来修饰变量、函数、构造函数。一旦以上任何元素被constexpr修饰,那么等于说是告诉编译器 “请大胆地将我看成编译时就能得出常量值的表达式去优化我”。编译器优化过程中便会发现错误。

const int func() {
return ;
}
main(){
int arr[func()];
}
//error : 函数调用在常量表达式中必须具有常量值

告诉编译器返回的是个“常数”,所以,不会报错了。

constexpr func() {
return ;
}
main(){
int arr[func()];
}
//编译通过

为了性能

放在 stack上的数组也是可以的,比如main中的如下:
int main()
{
int i;
cin >> i;
int arr[i];
}

跟const无关,而是使用了C99的一个特性,名叫variable length array(简称VLA)。

而为什么我们需要constexpr呢?那就是为了性能。

其他链接

When should you use constexpr capability in C++11?

When should literal classes be used in C++?

Want speed? Use constexpr meta-programming! [static的方式是最快的]

三、字面类型 (LiteralType)

字面量 类型

Ref: C++ literal type

要区分 literal 和 literal-type 这两个不同的概念。

literal:文字量,10,3.14, true ,u8"123",  L"好"这些东西。

literal-type: 参考http://en.cppreference.com/w/cpp/concept/LiteralType  简单的说,就可以在用于编译期运算的对象。

标量 类型

对于标量,例如int,显然可以参与 编译期运算,例如:constexpr int fac( int N);  //计算阶乘。所以标量都是属于literal-type。

从这里可以看出,literal-type仅仅是类型系统中,一个catalog。所有的类型,要么归类到literal-type,要么归类到none-literal-type。

现在class,也能归类于literal-type,只要满足一些条件:

是否是 literal type?

// is_literal_type example
#include <iostream>
#include <type_traits> struct A { };
struct B { ~B(){} }; int main() {
std::cout << std::boolalpha;
std::cout << "is_literal_type:" << std::endl;
std::cout << "int: " << std::is_literal_type<int>::value << std::endl;
std::cout << "int&: " << std::is_literal_type<int&>::value << std::endl;
std::cout << "int*: " << std::is_literal_type<int*>::value << std::endl;
std::cout << "A: " << std::is_literal_type<A>::value << std::endl;
std::cout << "B: " << std::is_literal_type<B>::value << std::endl;
return ;
}

Output:

is_literal_type:
int: true
int&: true
int*: true
A: true
B: false

End.

最新文章

  1. NHibernate系列文章目录
  2. 初学c# -- 学习笔记(三)
  3. JSP page指令详解
  4. 修改Netbeans默认使用UTF-8编码
  5. [HIHO1082]然而沼跃鱼早就看穿了一切(字符串水题)
  6. 开发ffmpeg/live555常见问题错误及解决方法
  7. HDU 5622 KK&#39;s Chemical DP
  8. 自动化测试(四):VBScript脚本语言
  9. Microsoft Word Regular Expression
  10. 一款js、css压缩工具yuicompressor
  11. alsa音频驱动科普第一课
  12. FFT 的C 语言
  13. iOS开发系列-九宫格算法-xib
  14. kafka消息中间件及java示例
  15. 表达式求值(栈方法/C++语言描述)(三)
  16. FreeMarker的用法
  17. Oracle亿级数据查询处理(数据库分表、分区实战)
  18. sublime3 破解
  19. Ionic后退刷新
  20. 使用API失效供应商地址Demo(转)

热门文章

  1. spring静态代理
  2. 编写一个基本的连接池来实现连接的复用&amp;一些工程细节上的优化
  3. Android应用安全开发之浅谈加密算法的坑
  4. MySQL 启动原理剖析
  5. 辛巴学院-Unity-剑英的c#提高篇(一)主循环
  6. Win8 Metro动态加载内容框架
  7. 使用C#给Linux写Shell脚本(下篇)
  8. 你可能不知道的7个CSS单位
  9. ASP.NET MVC 5 - 查询Details和Delete方法
  10. Azure PowerShell (4) 使用PowerShell管理多个订阅