4

cppreference

当复制省略发生时,实现将省略的复制/移动 (C++11 起) 操作的源和目标视为简单地引用同一对象的两种不同方式,并且该对象的销毁发生在后面的两个对象在没有优化的情况下被销毁的时间(除了,如果所选构造函数的参数是对对象类型的右值引用,则在目标被销毁时发生销毁)(C++17 起)。

对于像这样的简单情况A a = returnA();,我可以理解该对象没有被销毁,而是像后来returnA()的情况一样发生了销毁。A a;

我想不出一种相反的情况,即复制/移动操作的源首先被破坏。我还想要一个自 C++17 以来添加的语句的示例(当所选构造函数的参数是对对象类型的右值引用时例外)

4

1 回答 1

3

源比目标长的对称情况是纯右值是一个参数:

struct A {
  static int *data;
  A() {if(!refs++) data=new int(42);}
  A(const A&) {++refs;}  // not movable
  ~A() {if(!--refs) delete data;}
private:
  static int refs;
};
int A::refs,*A::data;
int* f(A) {return A::data;}
A returnA();
int returnInt() {return *f(returnA());} // ok

因为 的结果returnA()是临时的,所以它的生命周期会延伸到return语句的full-expression的末尾。实现可以用 's 参数标识它f,但在f返回时可能不会破坏它,因此取消引用returnInt是有效的。(请注意,参数可能仍然存在那么久。)

C++17 中的调整(以及保证这样的省略)是,如果你(将)移动纯右值,它可能会在参数为时被破坏(因为你不应该依赖它的内容)。如果那是f返回的时候,如果将上面的(不明智的)代码变为A可移动的,则该代码将变为无效。

于 2018-12-14T18:46:52.063 回答