为什么C++中[=]捕获的lambda会生成多份tester对象拷贝?
问题解答
1. 多份临时tester拷贝产生的原因
你看到的多份拷贝来自两个环节:
- 第一份拷贝是
[=]值捕获产生的:值捕获会将栈上的t拷贝一份,作为lambda对象的成员变量。 - 其余临时拷贝来自
std::thread的传参逻辑:std::thread构造函数需要把传入的可调用对象(也就是你的lambda)持久化存储到线程内部的内存空间,避免主线程栈上的lambda销毁后线程访问非法地址。由于你没有给tester类定义移动构造函数,lambda的移动操作被抑制,所有传递过程都只能走拷贝构造。在编译器没有做复制消除的情况下,参数传递过程中产生的临时lambda对象就会带来额外的tester拷贝,这些临时对象在传递完成后就会立即销毁,也就是你看到的那些很快被析构的实例。
2. MSVC和GCC输出差异的原因,是否为未定义行为
这是完全合法的实现差异,不属于未定义行为。
C标准仅要求std::thread构造函数最终会把可调用对象拷贝到内部持久存储,没有限制参数传递过程中允许的临时拷贝次数,也没有强制要求编译器必须做复制消除。MSVC的STL实现和GCC使用的libstdc对std::thread的参数传递逻辑、默认优化策略不同,就导致了拷贝次数的差异。
如果开启编译优化(MSVC加/O2参数、GCC加-O2参数),编译器会触发复制消除规则,去掉不必要的临时拷贝,最终大概率只会保留1次必要的拷贝。
内容的提问来源于stack exchange,提问作者MHebes
相关产品推荐
相关产品推荐

