c++ - 为什么这个构造函数在传递给 std::thread 时被调用了 3 次?
问题描述
考虑这段代码:
class Widget {
public:
Widget() { coutDefaultCtor(); }
Widget(const Widget& w) { coutCopyCtor(); }
Widget(Widget&& w) { coutMoveCtor(); }
~Widget() = default;
void coutDefaultCtor() {
std::cout << " called default Widget ctor " << std::endl;
}
void coutMoveCtor() {
std::cout << " called move Widget ctor " << std::endl;
}
void coutCopyCtor() {
std::cout << " called copy Widget ctor " << std::endl;
}
void doSomething() const { }
};
void takeWidget(const Widget& ref) {
ref.doSomething();
}
int main() {
Widget widget;
std::thread t(takeWidget, widget);
t.join();
// expect 2 ctor calls
// but calls 3
}
据我所知,std::thread
将始终按值复制参数。如果在某种情况下,入口点函数被定义为采用 r-value 或 const l-value 引用(此处相同),则在内部将创建一个临时类型并作为 r-value 传递。
上面代码的输出打印了" called Widget ctor "
3 次。每个构造函数、默认值、复制和移动一个。
我只期待 2 次,一次用于widget
调用默认构造函数main()
,而创建的临时构造函数std::thread
又被移动,为什么这里会发生另一个看似额外的构造?
解决方案
它是 C++ 标准库的一个实现细节,在不同的实现中可能会有所不同。std::thread t(takeWidget, widget)
除了简单地调用之外,还有更多的事情发生takeWidget(widget)
。例如,在 GCC 实现中,thread
构造函数调用make_tuple()
将根据参数类型移动或复制参数。
推荐阅读
- jenkins - 如何在 Jenkins Pipeline 中手动选择环境
- c - 将枚举存储在有符号字符中并在 C 中与枚举进行比较失败
- jprofiler - JProfiler:内存分析需要帮助 - 我在哪里可以找到分配对象的行号
- c++ - Visual Studio 删除共享的 .pch 文件,以及有关自定义构建步骤的问题
- excel - 删除具有条件列的行中的特定单词
- javascript - 从父元素的子元素获取类值
- c++ - 将二维数组指针参数分配给局部数组指针变量
- python - Attension Layer Tensorflow TypeError:无法迭代具有未知第一维的张量
- salesforce - 闪电组件recordUpdated方法绑定触发stale data事件
- google-kubernetes-engine - GKE Stackdriver 中 Dropwizard 指标的最新最佳实践