【问题标题】:When is the copy constructor for the return value happens返回值的复制构造函数何时发生
【发布时间】:2016-10-06 03:47:09
【问题描述】:

我有以下成员函数:

Person ClassB::DoSomethingAndReturnPerson()
{
 RAIIMutex myLock(&m_mutex);
 return m_person;
}

RAIIMutex 是一个辅助类,它接收互斥体并将其锁定在构造函数中并在析构函数中释放。

m_personPerson 类型(尺寸非常小)。其他线程中的其他函数可能会更改此成员。

我想按值返回m_person(返回一个副本),当然我想避免m_person在另一个线程中被更改而在返回中被复制的情况,所以我添加了锁.

但是首先会发生什么呢?编译器是先创建m_person 的副本还是先调用myLock 的析构函数?

理论上,这样做很容易解决:

Person ClassB::DoSomethingAndReturnPerson()
{
 RAIIMutex myLock(&m_mutex);
 Person tmp = m_person;
 return tmp;
}

但我很想知道我的问题的答案。

谢谢

【问题讨论】:

  • [OT] 你可以用std::lock_gurad替换RAIIMutex
  • 由于copy elision,可能根本不会调用复制构造函数。
  • @JoachimPileborg 这值得怀疑,因为m_person 似乎是一个类成员变量。

标签: c++ return language-lawyer


【解决方案1】:

之前会处理返回值的复制初始化。

从标准来看,[stmt.return]/3(强调我的)

调用结果的复制初始化顺序在之前 完整表达结束时的临时性破坏 由 return 语句的操作数建立,反过来,是 在破坏局部变量([stmt.jump])之前排序 包含 return 语句的块

【讨论】:

【解决方案2】:

本地对象的析构函数在“代码的最后一行”之后调用。这是来自标准 (3.7.3 / 3) 的相关引用:

如果具有自动存储持续时间的变量具有初始化或 有副作用的析构函数,在结束前不能被销毁 它的块,也不应该作为优化被淘汰,即使它 似乎未使用,除了类对象或其复制/移动可能 按照 12.8 的规定被淘汰

【讨论】:

  • 那么它会发生在复制构造函数之前还是之后?复制构造函数不是我的代码的一部分,编译器会处理它
  • OopsUser,@songyuanyao 的回答提供了更好的报价。在复制构造函数之后,如果它被调用的话。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
  • 1970-01-01
  • 1970-01-01
  • 2017-11-28
  • 2016-10-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多