C++17 复制省略和对象销毁

C++17 copy elision and object destruction

来自 cppreference,

When copy elision occurs, the implementation treats the source and target of the omitted copy/move (since C++11) operation as simply two different ways of referring to the same object, and the destruction of that object occurs at the later of the times when the two objects would have been destroyed without the optimization (except that, if the parameter of the selected constructor is an rvalue reference to object type, the destruction occurs when the target would have been destroyed) (since C++17).

对于像 A a = returnA(); 这样的简单情况,我可以理解对象在 returnA() 中没有被销毁,而是像 A a; 的情况那样发生销毁,这是较晚的时间.

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

当 prvalue 是参数时,源比目标长的对称情况:

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 语句的 完整表达式 的末尾。实现可以用f的参数标识它,但在f returns时可能不会销毁它,所以returnInt中的解引用是有效的。 (注意参数 may survive that long 无论如何。)

C++17 中的调整(连同保证这种省略)是如果您(将)移动 纯右值,当参数为 (因为无论如何你都不应该依赖它的内容)。如果那是 f returns 时,如果 A 可移动,上面的(不明智的)代码将变得无效。