C++11中删除拷贝构造的函数对象与lambda传递编译差异疑问
二者编译行为差异的核心原因是两种可调用对象的拷贝构造函数可用性不同,具体解释如下:
1. 自定义abc结构体编译失败的原因
你在abc的定义中显式删除了拷贝构造函数:abc(const abc&) = delete;,直接禁用了该类型的拷贝能力。
而print函数的形参Func f是值传递,调用print(s)时需要将实参s拷贝构造到形参f,调用了被删除的函数,因此编译报错。
2. 无捕获lambda编译成功的原因
你之前对lambda的认知存在偏差:lambda并非天生没有拷贝构造函数,C++标准对lambda类型的特殊成员函数生成规则有明确规定:
- 无任何捕获变量的lambda,编译器会隐式生成默认可用的拷贝构造、移动构造、拷贝赋值、移动赋值函数
- 只有当lambda按值捕获的对象中存在不可拷贝的类型时,lambda的拷贝构造才会被隐式删除
你给出的lambda示例没有捕获任何变量,所以它的拷贝构造函数是正常可用的,值传递给print的形参时可以正常完成拷贝操作,因此编译可以正常通过。
补充验证
你可以测试下面的代码,当lambda捕获不可拷贝的对象时,会表现出和abc完全一致的编译失败行为:
template <typename Func> void print(Func f) { f(); } struct abc { abc() = default; abc(const abc&) = delete; abc& operator=(const abc&) = delete; }; int main() { abc s; auto f = [s]() { // 按值捕获不可拷贝的abc对象,lambda的拷贝构造被隐式删除 std::cout << "f" << std::endl; }; print(f); // 这里触发拷贝构造调用,编译报错 return 0; }
内容的提问来源于stack exchange,提问作者user3689963
相关产品推荐
相关产品推荐

