C++ constexpr
1、constexpr
1、const与constexpr:
const: 承若不改变这个值,主要用于说明接口,这样在把变量传入函数时就不必担心变量会在函数内被改变了,编译器负责确认并执行const的承若。
constexpr:在编译时求值,主要用来说明常量,作用是允许将数据置于只读内存中以及提升性能。
常量表达式指由编译器求值的表达式。
//使用const定义常量
const int x = 7; //
const string s = "hello"; //
const int y = sqrt(x);
//使用constexpr定义常量
constexpr int xx = x; //OK
constexpr string ss = s; //错误:string不是字面值常量类型
constexpr int yy = y; //错误:sqrt(x)不是constexpr函数
以常量表达式初始化的const可以用在常量表达式中,与constexpr不同的是,const可以用非常量表达式初始化,但此时该const将不能用作常量表达式。
通常情况下,当定义简单的常量时,constexpr比const要好。
2、字面值常量类型
struct Point
{
int x, y, z;
constexpr Point up(int d)
{
return {x, y, z + d};
}
constexpr Point move(int dx, int dy)
{
return {x + dx, y + dy};
}
};
含有constexpr构造函数的类称为字面值常量类型。构造函数必须足够简单才能声明为constexpr,即它的函数体必须为空且所有成员都是用潜在的常量表达式初始化的。
对于成员函数来说,constexpr隐含了const的意思。所以下面这种写入是没有必须要的:
constexpr Point move(int dx, int dy) const
{
return {x + dx, y + dy};
}
通过使用字面值类型, 我们可以令constexpr函数适应用户自定义的类型。
3、constexpr 函数
在函数定义中出现constexpr时,它的含义:如果给定了常量表达式作为实参,则该函数应该能用在常量表达式中。
在对象定义中出现constexpr时,它的含义:在编译时对初始化器求值。
constexpr int fac(int n)
{
return (n > 1) ? n * fac(n - 1) : 1;
}
void f(n)
{
int f5 = fac(5); //可能在编译期求值
int fn = fac(n); //在运行时求值(n是变量)
constexpr int f6 = fac(6); //必须在编译期求值
constexpr int fnn = fac(n); //错误:无法在编译期求值
char a[fac(4)]; //数组的尺寸必须是常量,fac(4)是常量
char a2[fac(n)]; //错误:数组的尺寸必须是常量,而n是变量
}
函数必须足够简单才能在编译期求值:
- constexpr函数必须包含一条独立的return语句。
- constexpr不能有循环,也不能有局部变量。
- constexpr函数不能有副作用,constexpr函数应该是一个纯函数。
以下是一些错误的示例:
int glob;
constexpr void bad1(int a) //错误: constexpr函数不能使void
{
glob = a; //错误: constexpr函数有副作用
}
constexpr int bad2(int a)
{
if( a > 0) return a; //错误: constexpr有if语句
else return -a;
}
constexpr int bad3(int a)
{
int sum = 0; //错误: 有局部变量
for(int i = 0; i < a; ++i) //错误: 有for循环
sum += fac(i);
return sum;
}
4、constexpr与引用
constexpr函数不允许有副作用,因此我们不能向非局部对象写入内容,反过来说,只要我们不向非局部对象写入内容,就能使用它。
示例:
constexpr int ftb[]{1, 2, 3, 5,8, 13};
constexpr int fib(int n)
{
return (n < sizeof(ftb)/sizeof(*ftb)) ? ftb[n] : ftb[sizeof(ftb)/sizeof(*ftb) - 1];
}
constexpr 函数可以接收引用实参,尽管它不能通过这些引用写入内容,但是const引用参数同样有用。
template<>
class complex<float>
{
public:
//...
explicit constexpr complex(const complex<double> &);
//...
}
//
constexpr complex<float> z{2.0};
//其中逻辑上用于存储const引用实参的临时变量成了编译器内部可用的一个值
5、条件求值
constexpr函数之外的条件表达式不会在编译期求值。
constexpr int check(int i)
{
return (low <= i && i < high) ? i : throw out_of_range();
}
//其中我们假设low和high值是设计时未知,而编译时已知的参数。
constexpr int low = 0;
constexpr int high = 99;
C++ constexpr的更多相关文章
- C++11特性——变量部分(using类型别名、constexpr常量表达式、auto类型推断、nullptr空指针等)
#include <iostream> using namespace std; int main() { using cullptr = const unsigned long long ...
- [c++] constexpr and literal class
稀奇古怪的新特性,菜鸟在此啄上一啄. 1. When should literal classes be used in C++? 2. int i; // not constant const ...
- C++之内联函数与constexpr
inline 函数 规模小,流程直接且频繁调用 cout<<shortString(s1,s2)<<endl; = cout<<(s1.size()<s2.s ...
- Item 15: 只要有可能,就使用constexpr
本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 如果说C++11中有什么新东西能拿"最佳困惑奖" ...
- c++基础 - constexpr
const expression常量表达式,指值不会改变,并且在编译过程中就能得到计算结果的表达式. 复杂系统难以分辨一个初始值是否是常量表达式,因此提出constexptr以提示编译器,用来验证变量 ...
- constexpr和常量表达式
常量表达式:值不会改变并且在编译过程就能得到计算结果的表达式. 字面值属于常量表达式,用常量表达式初始化的const对象也是常量表达式. 一个对象(或表达式)是不是常量表达式由它的数据类型和初始值共同 ...
- 【C++】C++中const与constexpr的比较
先说结论相同点:const和consexpr都是用来定义常量的.不同点:const声明的常量,初始值引用的对象不一定是一个常量:constexpr声明的常量,初始值一定是常量表达式. constexp ...
- C++11 constexpr常量表达式
常量表达式函数 要求: 函数体内只有单一的return返回语句 例如: constexpr int data() { const int i=1; //含有除了return以外的语句 return i ...
- 常量表达式和constexpr(c++11)
常量表达式 常量表达式是指值不会改变且在编译阶段就能得到计算结果的表达式(两点要求) ; //是常量表达式 ; //是常量表达式 "; const int siz=s.size(); //不 ...
- c++ 11 游记 之 decltype constexpr
title: c++ 11 游记 1 keyword :c++ 11 decltype constexpr 作者:titer1 zhangyu 出处:www.drysaltery.com 联系:130 ...
随机推荐
- Cloud Computing——Everything as a Service
service 分类 有Iaas, Paas, SaaS HDFS 总结☞: HDFS应付不了的场景 无法低时延 小文件存储存在空间利用率问题 文件不可修改 三副本有什么作用 防止单机故障,提高可用性 ...
- 如何将python源文件打包成exe文件
PyInstaller是一个十分有用的第三方库,它能够在Windows.Linux.Mac OS X 等操作系统下将 Python 源文件打包,通过对源文件打包,Python 程序可以在没有安装 Py ...
- java把含小数点的数字字符串转换为int类型
String num ="1.00"; int abc =Double.valueOf(num).intValue();//转换为Int类型
- Spring Boot教程(三)消费Restful的web服务
构架工程 创建一个springboot工程,去消费RESTFUL的服务.这个服务是 http:///gturnquist-quoters.cfapps.io/api/random ,它会随机返回Jso ...
- 2019 南京网络赛A
南京网络赛自闭现场 https://nanti.jisuanke.com/t/41298 二维偏序经典题型 二维前缀和!!! #include<bits/stdc++.h> using n ...
- B. Array K-Coloring
B. Array K-Coloring 给定一个数组 要求对元素进行染色,满足相同元素颜色一定不同,且所有颜色要全部用完 #include<bits/stdc++.h> using nam ...
- [CSP-S模拟测试]:Smooth(数学)
题目传送门(内部题84) 输入格式 两个整数$B,K$ 输出格式 一个整数表示答案 样例 样例输入: 5 100 样例输出: 数据范围与提示 对于$40\%$的数据,保证答案小于$10^7$对于另$2 ...
- rollup的学习
概述(Overview) Rollup 是一个 JavaScript 模块打包器,可以将小块代码编译成大块复杂的代码,例如 library 或应用程序.Rollup 对代码模块使用新的标准化格式,这些 ...
- Js自定义数组map之bigmap
/** * like map,but prev,curr,next and index will be given * @param {Function} cb Callback,the parame ...
- mysq远程连接报错,host..
在本机登入mysql后,更改"mysql"数据库里的"user"表里的"host"项,从"localhost"改为'%' ...