为什么三元运算符会阻止返回值优化?

Chr*_*ckl 11 c++

为什么三元运算符会阻止MSVC中的返回值优化(RVO)?考虑以下完整的示例程序:

#include <iostream>

struct Example
{
    Example(int) {}
    Example(Example const &) { std::cout << "copy\n"; }
};

Example FunctionUsingIf(int i)
{
    if (i == 1)
        return Example(1);
    else
        return Example(2);
}

Example FunctionUsingTernaryOperator(int i)
{
    return (i == 1) ? Example(1) : Example(2);
}

int main()
{
    std::cout << "using if:\n";
    Example obj1 = FunctionUsingIf(0);
    std::cout << "using ternary operator:\n";
    Example obj2 = FunctionUsingTernaryOperator(0);
}
Run Code Online (Sandbox Code Playgroud)

使用VC 2013编译如下: cl /nologo /EHsc /Za /W4 /O2 stackoverflow.cpp

输出:

using if:
using ternary operator:
copy
Run Code Online (Sandbox Code Playgroud)

显然,三元运算符以某种方式阻止了RVO.为什么?为什么编译器不够聪明,看不到使用三元运算符的函数与使用if语句的函数做同样的事情,并相应地进行优化?

Ama*_*eus 5

查看程序输出,在我看来,编译器确实在这两种情况下都忽略了,为什么?

因为,如果没有激活 elide,正确的输出将是:

  1. 在函数返回时构造示例对象;
  2. 将其复制到临时;
  3. 将临时文件复制到 main 函数中定义的对象。

所以,我希望在我的屏幕上至少有 2 个“复制”输出。事实上,如果我执行你的程序,用 g++ 编译,用 -fno-elide-constructor,我从每个函数中得到 2 个复制消息。

有趣的是,如果我对 clang 做同样的事情,当函数FunctionUsingTernaryOperator(0);被调用时我会收到 3 个“复制”消息,我猜这是由于编译器如何实现三元。我猜它正在生成一个临时来解决三元运算符并将这个临时复制到 return 语句。