强制复制省略?gcc 5.4.1

fdg*_*dfg 1 c++ gcc c++11

我目前正在努力使用c ++和copy elision,特别是"命名返回值优化"(NRVO),以便能够实现工厂功能模式.我不能在不同的编译器中获得一致的行为.我的妈妈:

#include <iostream>
struct base {
  virtual ~base() { std::cout << "dtor base\n"; }
};
struct derived : public base {
  ~derived() { std::cout << "dtor derived\n"; }
};
derived f() { return derived(); }
int main(int argc, char *argv[]) {
  std::cout << "start\n";
  new derived(f());
  std::cout << "done. should have leaked!\n";
}
Run Code Online (Sandbox Code Playgroud)

注意:删除虚拟base-dtor可以解决问题,但我需要它才能实现真正的实现.

如果是gcc 5.4.0,则调用dtor,不执行复制省略:

$ g++ test2.cpp && ./a.out
start
dtor derived
dtor base
done. should have leaked!
Run Code Online (Sandbox Code Playgroud)

当使用gcc 5.4.1(Ubuntu称之为5.4.1,我认为这是svn-head)时,我可以接触到的所有clang以及各种其他gcc执行elision并成功泄漏内存:

$ g++ test2.cpp  && ./a.out
start
done. should have leaked!
Run Code Online (Sandbox Code Playgroud)

当我读到internetz上的不同位置时,编译器可以进行复制省略但不是必需的.只有c ++ 17引入了有保证的复制省略.这是gcc 5.4.0中的一个错误,还是只是以不同的方式实现标准?

Ser*_*eyA 5

复制elision是一个可选的优化,直到C++ 17,甚至在C++ 17中,它只在某些情况下是强制性的.据我所知,(N)即使在C++ 17中,RVO复制省略也不是强制性的 - 唯一强制的复制省略是临时初始化.

(N)RVO永远不应该改变你的程序的行为,并且永远不需要你的程序正常运行.无论(N)RVO如何,您都应该以适当的方式编写代码,并且当/ if(N)RVO启动时,只需更快地工作.

  • @fdgsydfgsdfgsdfg为了澄清,(N)如果程序依赖于临时创建和副作用,RVO可以改变程序的行为.SergeyA的观点是,你的程序永远不应该依赖于这样的副作用,如果没有,(N)RVO不会改变行为. (2认同)