其他分享
首页 > 其他分享> > c – 是否应该保证复制省略?

c – 是否应该保证复制省略?

作者:互联网

我不明白gcc在这里的行为,我希望RVO可以应用,但不管我是否通过优化标志和/或我通过-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()

解决方法:

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来获得这个elision的机会.

标签:copy-elision,c,c17
来源: https://codeday.me/bug/20190727/1549746.html