【发布时间】:2018-05-30 13:58:00
【问题描述】:
我不明白 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()
【问题讨论】:
-
RVO 不是只保证匿名对象吗?
bar和baz都有命名实例 -
@UnholySheep 在这种情况下,clang 对 NRVO 的生命周期分析看起来更好。我们不知道 gcc 版本。
-
NRVO 没有保证。所以两者都是有效的,只是 clang 做得更好。
标签: c++ c++17 copy-elision