为什么参数在构造 std::thread 时移动了两次
Why arguments moved twice when constructing std::thread
考虑这个程序,它本质上创建了 std::thread
,它调用函数 func()
,并以 arg
作为参数:
#include <thread>
#include <iostream>
struct foo {
foo() = default;
foo(const foo&) { std::cout << "copy ctor" << std::endl; }
foo(foo&&) noexcept { std::cout << "move ctor" << std::endl; }
};
void func(foo){}
int main() {
foo arg;
std::thread th(func, arg);
th.join();
}
我的输出是
copy ctor
move ctor
move ctor
据我了解,arg
在线程对象内部被复制,然后作为右值(移动)传递给 func()
。所以,我希望一次复制构造和一次移动构造。
为什么会有二次移动构造?
您按值将参数传递给 func
,这应该构成第二步。显然 std::thread
在调用 func
之前在内部再存储一次,这 AFAIK 在标准方面是绝对合法的。
So, I expect one copy construction and one move construction.
标准实际上并没有这样说。允许实现执行额外的内部移动构造。
虽然这样做可能效率较低。这是 https://gcc.gnu.org/PR69724 并且已针对即将发布的 GCC 10 版本进行修复。
考虑这个程序,它本质上创建了 std::thread
,它调用函数 func()
,并以 arg
作为参数:
#include <thread>
#include <iostream>
struct foo {
foo() = default;
foo(const foo&) { std::cout << "copy ctor" << std::endl; }
foo(foo&&) noexcept { std::cout << "move ctor" << std::endl; }
};
void func(foo){}
int main() {
foo arg;
std::thread th(func, arg);
th.join();
}
我的输出是
copy ctor
move ctor
move ctor
据我了解,arg
在线程对象内部被复制,然后作为右值(移动)传递给 func()
。所以,我希望一次复制构造和一次移动构造。
为什么会有二次移动构造?
您按值将参数传递给 func
,这应该构成第二步。显然 std::thread
在调用 func
之前在内部再存储一次,这 AFAIK 在标准方面是绝对合法的。
So, I expect one copy construction and one move construction.
标准实际上并没有这样说。允许实现执行额外的内部移动构造。
虽然这样做可能效率较低。这是 https://gcc.gnu.org/PR69724 并且已针对即将发布的 GCC 10 版本进行修复。