在您提供的代码示例中,emplace_back
和push_back
的行为与C++教程中描述的情况不符,这是因为您对lambda表达式的捕获方式有误解。
首先,我们来澄清一下emplace_back
和push_back
的区别:
push_back
接受一个值,这个值会被拷贝到vector的当前末尾。emplace_back
接受一个构造函数的参数列表,并在vector的当前末尾直接构造一个对象。
在您的代码中,当您使用push_back
时,您实际上是在创建一个std::function<void()>
对象,它内部包含一个指向A
的引用。这个引用会被拷贝到vector中,因此您看到了A copy
的输出。
对于emplace_back
,由于您传递的是一个lambda表达式[a](){}
,这里有一个常见的误解。Lambda表达式默认捕获外部作用域中的变量是按值捕获的。这意味着a
被拷贝了一次,并且lambda表达式内部存储的是a
的一个拷贝。
这里是问题的核心:
af.push_back([a](){}); // a被拷贝两次
// af.emplace_back([a](){}); // a被拷贝三次
push_back([a](){});
这里的[a]
是一个拷贝捕获,a
被拷贝到lambda表达式中,然后这个lambda表达式被拷贝到vector中。所以这里实际上是有两次拷贝:一次是创建lambda表达式,另一次是将lambda表达式添加到vector中。emplace_back([a](){});
这里[a]
同样是一个拷贝捕获,但是emplace_back
直接在vector的末尾构造了lambda表达式。这里并没有额外的拷贝,因为lambda表达式是在vector内部构造的。
所以,实际上emplace_back
并不会比push_back
多一次拷贝。如果您看到了emplace_back
比push_back
多一次拷贝的情况,那可能是因为其他原因,比如在打印消息时的输出顺序或者对lambda捕获的误解。
总结一下,在这个特定的例子中,push_back
和emplace_back
的行为应该是相同的,都涉及两次拷贝:一次是创建lambda表达式,另一次是将lambda表达式添加到vector中。