将Lambda作为std::vector::emplace_back参数的语法验证咨询
我来帮你拆解这段代码里的逻辑,搞清楚Lambda和std::vector::emplace_back配合的用法~
首先先把你的测试代码补全(加了必要的头文件和命名空间),方便看清楚:
#include <iostream> #include <vector> using namespace std; struct A { int a; A(){cout<<"constructed"<<endl;} A(const A& other){a = other.a; cout<<"copied"<<endl;} A(A&& other){a = other.a; cout<<"moved"<<endl;} // 这里提一句:原代码里的`const A&&`其实不太符合移动构造的常规写法,因为移动操作通常需要修改源对象,所以去掉const更合理 }; int main() { vector<A> vec; vec.emplace_back( []{A a; a.a = 1; return a; }()); A a2; a2.a = 2; vec.emplace_back(std::move(a2)); return 0; }
核心逻辑:Lambda不是直接传给emplace_back,而是执行后返回对象再传入
你写的[]{A a; a.a = 1; return a; }()里,后面的()是关键:
- 前面的
[]{...}是一个无捕获的Lambda表达式,它的功能是创建一个A对象、设置a=1然后返回这个对象。 - 后面的
()是立即调用这个Lambda,执行后会得到一个临时的A右值对象。 - 这个临时对象会被传给
emplace_back,而emplace_back的作用是在vector的内存空间里原地构造新元素——这里就会用这个临时右值,调用A的移动构造函数来创建vector里的第一个元素。
逐行分析输出(假设编译器开启常规优化)
- 执行
vec.emplace_back( []{A a; a.a = 1; return a; }()):- Lambda内部创建
A a,触发默认构造,输出constructed。 - Lambda返回
a时,因为a是局部对象,会被移动(或编译器RVO优化省略移动),然后emplace_back用这个返回的右值构造vector元素,触发移动构造,输出moved。
- Lambda内部创建
- 执行
A a2;:触发默认构造,输出constructed。 - 执行
vec.emplace_back(std::move(a2)):std::move(a2)把a2转为右值,emplace_back用它构造vector的第二个元素,触发移动构造,输出moved。
额外提醒:如果不加()会怎么样?
如果写成vec.emplace_back( []{A a; a.a = 1; return a; }),这才是把Lambda本身传给emplace_back,但vector的元素类型是A,Lambda的类型和A完全不匹配,编译器会直接报错——所以你加的()是让Lambda“变现”成A对象的关键。
内容的提问来源于stack exchange,提问作者Haytham
相关产品推荐
相关产品推荐

