push_back
和 emplace_back
是 C++ 中 std::vector
的两个成员函数,用于向容器末尾添加元素。它们的核心区别在于如何构造元素以及性能优化。
1. push_back
- 功能:
- 将元素添加到
vector
的末尾。 - 如果传递的是一个对象,
push_back
会调用该对象的拷贝构造函数或移动构造函数。 - 如果传递的是临时对象(右值),
push_back
会调用移动构造函数(如果存在)。
- 将元素添加到
- 性能:
- 如果传递的是左值对象,
push_back
会调用拷贝构造函数,可能导致额外的性能开销。 - 如果传递的是右值对象,
push_back
会调用移动构造函数,性能较好。
- 如果传递的是左值对象,
2. emplace_back
- 功能:
- 直接在
vector
的末尾就地构造元素,避免了不必要的拷贝或移动操作。 - 它通过传递的参数直接调用元素的构造函数。
- 直接在
- 性能:
emplace_back
直接在容器中构造对象,避免了临时对象的创建和拷贝/移动操作,性能通常优于push_back
。
3. 区别对比
特性 | push_back | emplace_back |
---|---|---|
参数类型 | 接受对象(左值或右值) | 接受构造对象所需的参数 |
构造方式 | 调用拷贝构造函数或移动构造函数 | 直接在容器中构造对象 |
性能 | 可能涉及临时对象的拷贝或移动 | 避免临时对象,性能更优 |
适用场景 | 适合已经构造好的对象 | 适合直接传递构造参数 |
4. 代码示例对比
使用 push_back
#include <vector>
#include <string>
int main() {
std::vector<std::string> vec;
std::string str = "Hello";
vec.push_back(str); // 调用拷贝构造函数
vec.push_back(std::move(str)); // 调用移动构造函数
return 0;
}
使用 emplace_back
#include <vector>
#include <string>
int main() {
std::vector<std::string> vec;
vec.emplace_back("Hello"); // 直接调用 std::string 的构造函数
return 0;
}
5. 性能优化示例
假设有一个类 MyClass
,其构造函数接受多个参数:
class MyClass {
public:
MyClass(int a, int b, int c) {
std::cout << "MyClass constructed" << std::endl;
}
};
- 使用
push_back
:std::vector<MyClass> vec; vec.push_back(MyClass(1, 2, 3)); // 先构造临时对象,再移动
- 使用
emplace_back
:std::vector<MyClass> vec; vec.emplace_back(1, 2, 3); // 直接在容器中构造对象
emplace_back
避免了临时对象的构造和移动,性能更优。
6. 总结
push_back
:- 接受一个对象(左值或右值),调用拷贝构造函数或移动构造函数。
- 适合已经构造好的对象。
emplace_back
:- 接受构造对象所需的参数,直接在容器中构造对象。
- 性能更优,适合直接传递构造参数。
在现代 C++ 中,优先使用 emplace_back
,尤其是当对象的构造参数已知时,可以避免不必要的拷贝或移动操作。
THE END
暂无评论内容