不应该保证复制省略适用吗?

Shouldn't guaranteed copy elision apply?

我不明白 gcc 在这里的行为,我希望 RVO 应用,但无论我是否传递优化标志 and/or 我传递 -std=c++17,在第二种情况下,无偿一对大括号似乎可以防止 GCC 删除副本。

$ cat /tmp/foo.cc
#include <iostream>
#define PING() std::cerr << __PRETTY_FUNCTION__ << '\n'

struct foo
{
  foo() { PING(); }
  ~foo() { PING(); }
  foo(const foo&) { PING(); }
};

foo bar()
{
  PING();
  foo res;
  return res;
}

foo baz()
{
  PING();
  {
    foo res;
    return res;
  }
}

int main()
{
  foo f1 = bar();
  foo f2 = baz();
}
$ g++-mp-7 -std=c++17 -O3 foo.cc
$ ./a.out
foo bar()
foo::foo()
foo baz()
foo::foo()
foo::foo(const foo&)
foo::~foo()
foo::~foo()
foo::~foo()

这不应该是保证复制省略的一部分吗? Clang 的行为符合我的预期:

$ clang++-mp-4.0 foo.cc
$ ./a.out
foo bar()
foo::foo()
foo baz()
foo::foo()
foo::~foo()
foo::~foo()

RVO(return 值优化)仅在您 return 来自函数的临时值时适用。在 barbaz 中,您都不是 return 临时工。相反,您 returning 一个 命名的 对象。这意味着您正在处理 NRVO(名为 return 值优化),并且不能保证并且更难做到。两个输出都符合标准,只是 clang 在优化方面比 gcc 做得更好。

来自https://en.cppreference.com/w/cpp/language/copy_elision

Under the following circumstances, the compilers are permitted, but not required to omit the copy- and move- (since C++11)construction of class objects even if the copy/move (since C++11) constructor and the destructor have observable side-effects. This is an optimization: even when it takes place and the copy-/move-constructor is not called, it still must be present and accessible (as if no optimization happened at all), otherwise the program is ill-formed.

  • If a function returns a class type by value, and the return statement's expression is the name of a non-volatile object with automatic storage duration, which isn't a function parameter, or a catch clause parameter, and which has the same type (ignoring top-level cv-qualification) as the return type of the function, then copy/move (since C++11) is omitted. When that local object is constructed, it is constructed directly in the storage where the function's return value would otherwise be moved or copied to. This variant of copy elision is known as NRVO, "named return value optimization".

不保证会发生 NRVO,但在您的情况下是有可能发生的。

正如 Sander De Dycker 在评论中指出的那样, 已经有一个bug report得到这个省略的机会了