在学习C++11线程std::thread的过程有这样一个场景。
#include <vector>
#include <thread>
void func() {}
int main()
{
std::vector<std::thread> threadlist;
std::thread trd{ func };
threadlist.push_back(std::move(trd));
return 0;
}
因为 std::thread 的实现中是删除了拷贝构造函数的,所有在调用 push_back 时需要传入一个右值,传入左值就会提示你拷贝构造已经被删除。
class thread {
...
public:
...
thread(const thread&) = delete;
thread& operator=(const thread&) = delete;
...
};
但是,在查看 vector 的代码时,发现 push_back 有两个重载函数,传入常量左值引用也不会导致拷贝发生,那么这个拷贝构造是发生在什么地方呢?
_CONSTEXPR20 void push_back(const _Ty& _Val) {
// insert element at end, provide strong guarantee
_Emplace_one_at_back(_Val);
}
_CONSTEXPR20 void push_back(_Ty&& _Val) {
// insert by moving into element at end, provide strong guarantee
_Emplace_one_at_back(_STD move(_Val));
}
在进行单步调式后,在一个 <xutility> 中找到了 construct_at 函数。
constexpr _Ty* construct_at(_Ty* const _Location, _Types&&... _Args) noexcept(
noexcept(::new(static_cast<void*>(_Location)) _Ty(_STD forward<_Types>(_Args)...))) /* strengthened */ {
_MSVC_CONSTEXPR return ::new (static_cast<void*>(_Location)) _Ty(_STD forward<_Types>(_Args)...);
}
在 return 的时候使用 placement new 指定内存生成。其中_Ty(_STD forward<_Types>(_Args)...)就调用了拷贝构造函数。
所以,如果你的结构体或类删除了拷贝构造函数,就需要给 push_back 传入一个右值。当然,你也可以直接使用 emplace_back,也不会有这样的问题了。