'constexpr'有什么用?
What are 'constexpr' useful for?
我真的找不到它的任何用处。我的第一个想法是,我可以使用它来实现"合同设计",而无需使用这样的宏:
struct S
{
S(constexpr int i) : S(i) { static_assert( i < 9, "i must be < 9" ); }
S(int i); //external defintion
char *pSomeMemory;
};
但这不会编译。我认为我们也可以使用它来引用同变量,而无需在我们想避免 get/setter 以使用户的一个成员的实例成为只读时创建额外的内存:
class S
{
private:
int _i;
public:
const int & constexpr i = _i;
};
但以上这些都没有真正编译。有人可以给我一些见解,为什么引入这个关键字?
constexpr
的目标取决于上下文:
-
对于对象,它表示对象是不可变的,应在编译时构造。除了将操作移动到编译时而不是在运行时创建
constexpr
对象之外,还有一个额外的优势,即在创建任何线程之前初始化它们。因此,他们的访问永远不需要任何同步。将对象声明为constexpr
的示例如下所示:constexpr T value{args};
显然,要做到这一点,
args
需要是常量表达式。 -
对于函数,它表示调用函数可以产生常量表达式。
constexpr
函数调用的结果是否生成常量表达式取决于函数的参数和定义。直接的含义是必须inline
函数(它将隐式地如此(。此外,在此类函数中可以执行的操作也存在限制。对于 C++11,函数只能有一个语句,对于非构造函数,该语句必须是return
语句。这一限制在C++14中放宽。例如,以下是constexpr
函数的定义:constexpr int square(int value) { return value * value; }
创建非内置类型的对象constexpr
相应的类型将需要constexpr
构造函数:生成的默认构造函数将不起作用。显然,constexpr
构造函数需要初始化所有成员。constexpr
构造函数可能如下所示:
struct example {
int value;
constexpr example(int value): value(value) {}
};
int main() {
constexpr example size{17};
int array[size.value] = {};
}
创建的constexpr
值可以在需要常量表达式的任何地方使用。
,constexpr
是一种将两种C++语言结合在一起的方法 - 一种在运行时运行,另一种在编译时运行。编译时编程通常称为元编程。
首先是C,它的宏。宏实际上是由编译器运行的小程序。他们有if语句(称为#ifdef
(,变量(带#define
(。甚至还有一种完整的脚本语言在编译时运行。
当C++出来时,它有C宏,仅此而已。然后是C++模板。这些引入了运行编译时代码的不同方法。C++元语言在很大程度上是功能性的,例如,允许你使用尾递归进行循环。
在C++ 11中,他们认为元编程可以看起来更好,因此他们引入了constexpr
。现在,您可以编写C++函数,这些函数也是元函数。在 C++ 14 中,情况变得更好,因为对 constexpr 函数的限制已经放宽。
Alex Allain在他的"Constexpr - C++11中的广义常量表达式"中的观点摘要,其中详细介绍了constexpr
的有用性:
- 首先,使用
constexpr
说明符,函数或变量的值可以在编译时。 constexpr
说明符的另一个好处是它可以用函数替换宏-
constexpr
也将使您的模板元编程受益。
对效率的好处:
常量表达式...允许某些计算在编译时进行,实际上是在代码编译时而不是在程序本身运行时进行。(阿兰2(
性能优势:如果某些事情可以在编译时完成,它将完成一次,而不是每次程序运行时
其他好处:
然后,可以在只允许编译时常量表达式的情况下使用此类变量和函数。对象声明中使用的 constexpr 说明符意味着 const。函数声明中使用的 constexpr 说明符意味着内联。(CPP 1(
constexpr
函数的规则:
- 它必须由单个返回语句组成(少数例外(
- 它只能调用其他 constexpr 函数
- 它只能引用 constexpr 全局变量 (Allain 6(
constexpr
构造函数的规则:
- 其每个参数都必须是文本类型
- 该类不得具有虚拟基类
- 构造函数不得具有函数尝试块 (CPP 6(
引文
Allain, Alex, "Constexpr - C++11 中的广义常量表达式", 未指定日期, "http://www.cprogramming.com/c++11/c++11-compile-time-processing-with-constexpr.html">
CPP,"Constexpr Specifier",2014 年 12 月 16 日,http://en.cppreference.com/w/cpp/language/constexpr
编辑:对不起,让我看起来像是这些观点的作者是我的错,所以我纠正了自己,更改了各个部分,并添加了引用以避免抄袭。
回答"有人能给我一些见解,为什么引入 constexpr 关键字?
现代C++支持两种类型的不变性。
1( 常量
2(共生。
constexper将在编译时进行评估。它用于指定恒常性,并允许将数据放置在可能损坏的内存中。
示例 1:
void UseConstExpr(int temp)
{
// This code snippet is OK
constexpr int y = max + 300;
std::cout << y << std::endl;
// This code snippet gives compilation error
// [ expression must have a constant value]
constexpr int z = temp + 300;
}
示例 2:
int addVector(const std::vector<int>& inVect)
{
int sum = 0;
for ( auto& vec : inVect)
{
sum += vec;
}
std::cout << sum << std::endl;
return sum;
}
int main()
{
// vInt is not constant
std::vector<int> vInt = { 1,2,3,4,5,6 };
// This code snippet is OK
// because evaluated at run time
const int iResult = addVector(vInt);
// Compiler throws below error
// function call must have a constant value in a constant expression
// because addVector(vInt) function is not a constant expression
constexpr int iResult = addVector(vInt);
return 0;
}
注:以上源码编译于VS2015
- Clang 8 带有静态 constexpr 和数组的链接器错误 - 错误是什么以及如何解决它?
- "constinit"和"constexpr"之间的真正区别是什么?
- [decl.constexpr].5 到底是什么意思?
- 静态自动 constexpr t = { "red" , "black" , "green" } 是什么类型;派生到?
- constexpr引用有什么用吗
- 有没有办法声明一个公共静态常量,该常量将使用 constexpr 在源文件中定义(有什么区别)?
- 有什么陷阱用 constexpr string_view 替换全局 const char[]?
- constexpr - "Evaluate value at compile time"到底是什么意思?
- constexpr静态成员什么时候停止成为constexpr
- 什么是 C++17 中的 constexpr 容器
- constexpr 标准函子的正确用法是什么?
- 什么时候 constexpr 实际上不是 constexpr
- 使用从不打算在常量表达式中使用的 constexpr 变量有什么好处吗?
- 什么是C++中的constexpr
- 将set函数(setter)标记为constexpr的目的是什么
- 有什么理由为什么“std::exchange”不是“constexpr”
- 内联和constexpr在标头中无捕获lambda有什么区别
- constexpr函数中允许什么
- 当在计算constexpr时抛出异常时会发生什么
- 在内联和 constexpr 功能的情况下"obey ODR"意味着什么?