4

假设我将 Visual Studio 或现代 GCC 与 -O2 一起使用。编译器会S在内部创建func()然后将其复制到 amy_result中,还是my_result使用构造函数(5, 6, 5 + 6)创建而不创建临时的S

注意: 函数func()定义及其用法位于单独的 .obj 文件中!

struct S
{
    S(int _x, int _y, int _z) : x(_x), y(_y), z(_z) { }
    int x, y, z;
};

S func(int a, int b)
{
    return S(a, b, a + b);
}


/// USAGE ///

S my_result = func( 5, 6 );
4

5 回答 5

8

现代编译器通常会优化这种操作。见返回值优化

于 2013-09-03T14:11:46.323 回答
2

这是一种优化,根据定义,它几乎意味着编译器是可选的,并且由每个特定的编译器决定要做什么。你怎么能确定呢?检查生成代码的反汇编!

也就是说,大多数编译器应该进行这种优化(返回值优化 [RVO]),因为在这种情况下它相对容易(没有多次返回,它是一个未命名的临时,所以你没有别名等)。

于 2013-09-03T14:05:11.597 回答
1

在我看来,提供的测试用例很简单,可以让RVO应用。

于 2013-09-03T14:05:18.080 回答
0

You can test this yourself, because the optimization in question has observable differences!

Most forms of optimization in C++ follow the as-if rule, which makes them difficult to detect. However, in a few cases, eliding (skipping) copy and move constructor is allowed, even if the difference results in observable behavior changes.

In this case, add the following to S:

struct S {
  // ...
  S( S const& o ):x(o.x), y(o.y), z(o.z) {
    std::cout << "copy ctor!\n";
  }
  S& operator=( S const& o ) {
    x=o.x;
    y=o.y;
    z=o.z;
    std::cout << "copy assign!\n";
    return *this;
  }
  S( S && o ):x(std::move(o.x)), y(std::move(o.y)), z(std::move(o.z)) {
    std::cout << "move ctor!\n";
  }
  S& operator=( S const& o ) {
    std::tie( x,y,z ) = std::tie( std::move(o.x),std::move(o.y),std::move(o.z) );
    std::cout << "move assign!\n";
    return *this;
  }
}

and run your code. With zero optimization you'll get copies and/or moves.

With any non-trivial level of optimization, the prints will disappear, because RVO (and, in related cases, NRVO) will run, eliminating the copies. (If your compiler isn't C++11, remove the move constructors above -- the optimization in C++03 was still allowed)

In C++11 you can explicitly construct the return value instead of relying on NRVO/RVO via the return {stuff} syntax.

Note that RVO (return value optimization) and NRVO (named return value optimization) are relatively fragile, and if you are relying on them you both have to understand how they work, what makes them break, and any quirks your particular compiler has in its implementation (if any).

于 2013-09-03T14:22:13.437 回答
0

我怀疑临时的优化了。您可以通过在构造函数和复制构造函数中放置打印语句来测试它,并查看在不同编译器设置下打印的内容。

于 2013-09-03T14:03:15.390 回答