C++ vector 中的 push_back() 和 emplace_back() 的区别及使用场景

科技   2024-11-20 18:43   上海  

在 C++ 标准库中,std::vector 是一种动态数组,它允许在运行时动态地增加或减少元素。在添加元素时,std::vector 提供了两种常用的方法:push_back()emplace_back()。尽管两者在表面上看起来相似,但它们在底层实现和使用场景上有所不同。

push_back()

push_back() 方法用于将一个元素添加到 vector 的末尾。这个方法接受一个参数,该参数是你要添加到 vector 中的元素的副本。因此,push_back() 会涉及到复制或移动构造函数的调用(取决于你传递给它的参数类型)。

#include <iostream>
#include <vector>
#include <string>

class MyClass {
public:
    MyClass(const std::string& name) : name_(name) {
        std::cout << "MyClass(" << name_ << ") constructed\n";
    }
    MyClass(const MyClass& other) : name_(other.name_) {
        std::cout << "MyClass(" << name_ << ") copy constructed\n";
    }
    MyClass(MyClass&& other) noexcept : name_(std::move(other.name_)) {
        std::cout << "MyClass(" << name_ << ") move constructed\n";
    }
    ~MyClass() {
        std::cout << "MyClass(" << name_ << ") destructed\n";
    }

private:
    std::string name_;
};

int main() {
    std::vector<MyClass> vec;
    MyClass obj("example");
    vec.push_back(obj);  // 调用复制构造函数
    return 0;
}

在上述代码中,push_back(obj) 会导致 obj 的复制构造函数被调用,因为 push_back() 需要一个元素的副本。

emplace_back()

emplace_back() 方法也是用于将元素添加到 vector 的末尾,但它是通过直接在 vector 的内存位置构造元素来实现的。这意味着你可以避免额外的复制或移动操作,特别是对于大型对象或那些复制/移动代价较高的对象,使用 emplace_back() 可以带来性能上的优势。

emplace_back() 接受与元素构造函数相同的参数,并直接在 vector 的内存位置调用元素的构造函数。

#include <iostream>
#include <vector>
#include <string>

class MyClass {
public:
    MyClass(const std::string& name) : name_(name) {
        std::cout << "MyClass(" << name_ << ") constructed\n";
    }
    ~MyClass() {
        std::cout << "MyClass(" << name_ << ") destructed\n";
    }

private:
    std::string name_;
};

int main() {
    std::vector<MyClass> vec;
    vec.emplace_back("example");  // 直接在 vector 的内存位置构造元素
    return 0;
}

在这个例子中,emplace_back("example") 直接在 vec 的内存位置构造了一个 MyClass 对象,没有涉及到复制或移动构造函数。

使用场景

  • **push_back()**:

    • 当你已经有一个现成的对象,并且希望将其添加到 vector 中时,可以使用 push_back()
    • 当对象的复制或移动代价较低时,push_back() 是一个不错的选择。
  • **emplace_back()**:

    • 当你需要构造一个对象并将其直接添加到 vector 中时,使用 emplace_back() 可以避免不必要的复制或移动操作。
    • 当对象的复制或移动代价较高时,emplace_back() 通常会提供更好的性能。
    • 当你使用复杂的类型(如包含智能指针或大型数据结构的类型)时,emplace_back() 可以帮助你避免不必要的临时对象创建和销毁。

总结

  • push_back() 需要一个对象的副本,会调用复制或移动构造函数。
  • emplace_back() 直接在 vector 的内存位置构造对象,避免了额外的复制或移动操作。
  • 根据你的具体需求(如对象的构造复杂度、复制/移动代价等),选择适当的方法来添加元素到 vector 中。

通过理解这两种方法的区别和使用场景,你可以编写出更高效、更简洁的 C++ 代码。


Qt教程
致力于Qt教程,Qt技术交流,研发
 最新文章