c++ 为什么std::thread可以返回但没有复制限制?

bvk5enib  于 2023-06-25  发布在  其他
关注(0)|答案(2)|浏览(202)

我对下面代码的成功编译感到非常困惑。函数'g'中的变量't'显然是左值。当'g'返回到main函数时,'t'应该被复制。但是,线程对象是不可复制的,那么为什么它能成功编译呢?

  1. #include <thread>
  2. void some_other_function(int) {
  3. return;
  4. }
  5. std::thread g()
  6. {
  7. std::thread t(some_other_function,42);
  8. return t;
  9. }
  10. int main() {
  11. g();
  12. return 0;
  13. }
9ceoxa92

9ceoxa921#

当你return一个局部变量时,将使用移动构造函数而不是复制构造函数(如果可用)。虽然std::thread没有复制构造函数,但它有一个移动构造函数,所以这将起作用。
请参见Automatic_move_from_local_variables_and_parameters
由于NRVO(命名返回值优化),编译器也可能完全省略移动,但这并不能保证。

wbrvyc0a

wbrvyc0a2#

代码编译是因为Named Return Value Optimization (NRVO),或者说是因为无法执行时发生的隐式移动。无论发生哪种情况,都不会使用复制构造函数。
这种技术可以在任何时候通过名称返回局部变量,例如:

  1. return t;

在你的例子中。可以将本地对象t视为函数外部的返回对象,因此不会调用移动或复制构造函数。如上所述,如果编译器不能执行NRVO,则移动构造函数是一个回退。std::thread是不可复制的,但是可以移动,所以这段代码可以工作。

  • 注意:对于既不可复制也不可移动的类,如std::mutex,您的代码将无法编译。*

相关问题