Gra*_*ers 25 c++ rationale c++11
根据广义常量表达式 - 修订版5,以下是非法的.
constexpr int g(int n) // error: body not just ‘‘return expr’’
{
int r = n;
while (--n > 1) r *= n;
return r;
}
Run Code Online (Sandbox Code Playgroud)
这是因为所有'constexpr'函数都必须具有这种形式{ return expression; }.我看不出有任何理由需要这样做.
在我看来,唯一真正需要的是不读取/写入外部状态信息,传入的参数也是'constexpr'语句.这意味着对具有相同参数的函数的任何调用都将返回相同的结果,因此可以在编译时"知道".
我的主要问题是,它似乎只是强迫你做一些真正的回旋形式的循环,并希望编译器优化它,以便它对非constexpr调用同样快.
要constexpr为上面的例子写一个有效的,你可以这样做:
constexpr int g(int n) // error: body not just ‘‘return expr’’
{
return (n <= 1) ? n : (n * g(n-1));
}
Run Code Online (Sandbox Code Playgroud)
但是这很难理解,你必须希望编译器在使用违反要求的参数调用时处理尾递归const-expr.
jal*_*alf 18
原因是编译器已经有很多工作,而且还不是一个成熟的解释器,能够评估任意C++代码.
如果他们坚持单一表达,他们会限制要大幅考虑的案件数量.松散地说,它简化了很多东西,特别是没有分号.
每次;遇到a 时,都意味着编译器必须处理副作用.这意味着在前面的语句中更改了某些本地状态,以下语句将依赖于该语句.这意味着被评估的代码不再仅仅是一系列简单的操作,每个操作都将前一个操作的输出作为输入,但也需要访问内存,这更难以推理.
简而言之,这个:
7 * 2 + 4 * 3
Run Code Online (Sandbox Code Playgroud)
很容易计算.您可以构建一个如下所示的语法树:
+
/\
/ \
* *
/\ /\
7 2 4 3
Run Code Online (Sandbox Code Playgroud)
并且编译器可以简单地遍历这个树,在每个节点上执行这些原始操作,并且根节点隐含地是表达式的返回值.
如果我们使用多行编写相同的计算,我们可以这样做:
int i0 = 7;
int i1 = 2;
int i2 = 4;
int i3 = 3;
int i4 = i0 * i1;
int i5 = i2 * i3;
int i6 = i4 + i5;
return i6;
Run Code Online (Sandbox Code Playgroud)
这很难解释.我们需要处理内存读写,我们必须处理return语句.我们的语法树变得复杂得多.我们需要处理变量声明.我们需要处理没有返回值的语句(例如,循环或内存写入),但只是在某处修改某些内存.哪个记忆?哪里?如果它意外地覆盖了一些编译器自己的内存怎么办?如果它是段错误怎么办?
即便没有一切讨厌的"假设的,编译器的代码来解释只是得到了很多更复杂.语法树现在看起来是这样的:(LD和ST分别加载和存储操作)
;
/\
ST \
/\ \
i0 3 \
;
/\
ST \
/\ \
i1 4 \
;
/\
ST \
/ \ \
i2 2 \
;
/\
ST \
/\ \
i3 7 \
;
/\
ST \
/\ \
i4 * \
/\ \
LD LD \
| | \
i0 i1 \
;
/\
ST \
/\ \
i5 * \
/\ \
LD LD \
| | \
i2 i3 \
;
/\
ST \
/\ \
i6 + \
/\ \
LD LD \
| | \
i4 i5 \
LD
|
i6
Run Code Online (Sandbox Code Playgroud)
它不仅看起来更复杂,而且现在也需要状态.之前,每个子树都可以单独解释.现在,他们都依赖于该计划的其余部分.LD叶子操作之一没有意义,除非它被放置在树中,以便ST先前在同一位置上执行操作.
为了防止这里出现任何混淆,您要知道constexpr函数/表达式是在编译时进行评估的.没有涉及运行时性能问题.
知道了这一点,他们只允许在constexpr函数中使用单个return语句的原因是编译器实现者不需要编写虚拟机来计算常量值.
我担心QoI问题.我想知道编译器实现者是否足够聪明来执行memoization?
constexpr fib(int n) { return < 2 ? 1 : fib(n-1) + fib(n-2); }
Run Code Online (Sandbox Code Playgroud)
没有memoization,上面的函数有O(2 n)的复杂性,即使在编译时,这肯定不是我想要的.
| 归档时间: |
|
| 查看次数: |
5988 次 |
| 最近记录: |