在C++中首先发生,返回对象或本地对象的析构函数的副本?

stu*_*stu 16 c++ multithreading

我想在某个地方有一个答案,但我找不到它,因为有很多线程问题,相比之下,我的相当简单.

我不是要创建线程安全的副本或赋值构造函数或类似的东西.

我想知道的是,如果我有一个表示互斥锁的类,并且我从一个实例化它的函数返回,这首先发生,我的互斥体的析构函数(因此解锁它)或返回值的复制构造函数.这是我的例子:

string blah::get_data(void)
  {
    MutexLock ml(shared_somewhere_else); // so this locks two threads from calling get_data at the same time

    string x = "return data";
    return x;
  }
Run Code Online (Sandbox Code Playgroud)

在其他地方,我们称之为get_data ...

 string result = get_data();
Run Code Online (Sandbox Code Playgroud)

回想一下C,我们永远不会返回指向全局变量的指针,因为返回后局部变量超出了范围.

C++没有这个问题,因为x会被复制到结果中.我想知道的是什么时候发生.在复制之前我的锁是免费的吗?

在这个简单的例子中,"返回数据"是静态信息,但我正在使用它,它的数据可以由另一个线程更改(也锁定在同一个MutexLock上),所以如果锁在释放之前释放了复制到结果制作,副本可能会被破坏.

我不确定我是否正在解释这个问题,所以我会试着澄清这是否有意义.

Rol*_*len 17

对于以前的标准(这里我将使用C++ 03),最接近标准来声明返回中的操作序列是从6.6

6.6跳转声明

  1. 在从范围退出(但是已完成)时,将为所有具有自动存储持续时间(3.7.2)(命名对象或临时值)的构造对象调用析构函数(12.4),这些对象在其范围内声明,其声明的顺序与其声明的顺序相反.从循环中移出一个循环,或者从具有自动存储持续时间的初始化变量返回过去涉及销毁具有自动存储持续时间的变量,这些变量在从...转移的点处的范围内.

必须完成return语句才能退出[function]范围,这意味着复制初始化也必须完成.此订单不明确.3.7.212.8中的各种其他引用简明扼要地陈述与上述相同而没有提供明确的顺序.工作修订(2014年11月之后)包括以下引用以解决该问题.该缺陷报告阐明了变化.

从该问题发布之日的标准的当前工作草案(N4527)

6.6.3退货声明

  1. 返回实体的复制初始化在由return语句的操作数建立的全表达式结束时临时销毁之前进行排序,然后在销毁本地变量(6.6)之前对其进行排序.封闭return语句的块.

请注意,此引用直接指6.6.所以我认为可以安全地假设在返回表达式复制初始化返回值之后,Mutex对象将始终被销毁.

  • 当然,通过[返回值优化](https://en.wikipedia.org/wiki/Return_value_optimization),可能不会创建实际的副本(它可能会直接构造到调用者的返回值空间中),但这在功能上是等效的当复制发生时,标准中描述的行为(无论哪种方式,它都在析构函数之前)。 (2认同)