测试了一个简单的utf8 strlen函数,并且很惊讶干线铿锵完全消除了它(gcc没有):
static int strlenutf8(const char* s)
{
int i = 0, l = 0;
while (s[i])
{
if ((s[i] & 0xc0) != 0x80) l++;
l++;
}
return j;
}
int main()
{
return strlenutf8("bla");
}
clang ++ -O3 -S -fverbose-asm:
main: # @main
.cfi_startproc
# BB#0: # %entry
movl $3, %eax
ret
这就像D的编译时功能评估。这在C ++中是否合法?
我的意思是最终必须有一个原因,他们首先发明了那些蹩脚的 constexpr 。由于受到严格限制,我甚至无法在这里使用它。
答案 0 :(得分:3)
constexpr
仅对常量表达式上下文(如模板参数推导)是必需的,但不保证在编译时评估constexpr
函数。
优化C ++程序的黄金法则是as-if
规则:
本国际标准中的语义描述定义了参数化的非确定性抽象机器。本国际标准对符合实施的结构没有要求。特别是,它们不需要复制或模拟抽象机器的结构。相反,需要符合实现来模拟(仅)抽象机器的可观察行为,如下所述。
用急需的脚注:
这项规定有时被称为“假设”规则,因为只要结果好像符合要求,实施可以自由地忽视本国际标准的任何要求,只要可以从程序的可观察行为。例如,实际实现不需要评估表达式的一部分,如果它可以推断出它的值没有被使用,并且没有产生影响程序的可观察行为的副作用。
使用主要的 BUT :具有副作用的复制构造函数(例如,它们增加“复制构造函数”,称为“计数变量”或等效项),不需要包含在“as-if”中。这包含在12.8/31
:
当满足某些条件时,允许实现省略类对象的复制/移动构造,即使对象的复制/移动构造函数和/或析构函数具有副作用。在这种情况下,实现将省略的复制/移动操作的源和目标视为仅仅两种不同的引用同一对象的方式,并且该对象的销毁发生在两个对象的后期时间。在没有优化的情况下销毁.123这种复制/移动的省略 在下列情况下允许进行称为复制省略的操作(可以合并以消除多份副本):[...]
答案 1 :(得分:2)
符合要求的C ++编译器必需通过在编译时计算表达式来支持constexpr
。 as-if规则对非constexpr
表达式的编译时评估允许;由于您的strlenutf8
函数没有(可见)副作用,因此允许编译器忽略它。
答案 2 :(得分:2)
您如何编写符合标准的C ++程序来检测此优化?如果你想不出办法,优化就可以了(好吧,好吧,如果没办法)。编译器不需要低效地执行操作,因为您可能会查看生成的代码。