Skip to content

[C++] vector 中使用 push_back() 和 emplace_back() 的差別

Last Updated on 2022-11-29 by Clay

今天在刷題的時候,看到一位分享自己解題思路的網友,他的程式碼中所有宣告的 vector 陣列,全部都使用 emplace_back()。那時候我可看不明白了,從我在大學上課開始寫時,老師都是教寫 push_back() 的啊?

實際上,emplace_back()push_back() 都是在陣列的尾端加入一個元素(element),但實際上,兩者的性能是存在著差距的。


效能比較

網路上每次談到這個這兩種吧同方式效能的話題,都會看到以下這段範例的程式碼。

#include<iostream>
#include<vector>
using namespace std;


class MyClass {
private:
    int x_ = 0;
    int y_ = 0;

public:
    MyClass(int x, int y) : x_(x), y_(y) {
        cout << "Create class" << endl;
    }

    ~MyClass() {
        cout << "Destroy class" << endl;
    }

    // Copy constructor
    MyClass(const MyClass& my_class) {
        cout << "Copy Constructor Called" << endl;
        x_ = my_class.x_;
    }

    // Move constructor
    MyClass (MyClass&& my_class) noexcept {
        cout << "Move Constructor Called" << endl;
        x_ = move(my_class.x_);
    }
};


int main() {
    vector<MyClass> v;
    v.reserve(2);

    cout << "\n--- push_back ---" << endl;
    v.push_back(MyClass(1, 2));

    cout << "\n--- emplace_back ---" << endl;
    v.emplace_back(1, 2);

    cout << "\n--- Finished ---" << endl;

    return 0;
}


Output:

--- push_back ---
Create class
Move Constructor Called
Destroy class

--- emplace_back ---
Create class

--- Finished ---
Destroy class
Destroy class


push_back() 是在容器(container)的尾端新增一個新的元素,接著再把要新增的『數值』移動、複製到該元素上。

emplace_back() 則是在容器的尾端直接建構(construct)新值的物件。所以,通常來說,使用 emplace_back() 會比 push_back() 來得更快。

那麼,我們是否就從此用 emplace_back() 來取代 push_back() 呢?

實際上,根據我的理解,存在著兩種情況最好不是輕易地使用 emplace_back() 來取代 push_back()

  1. 程式可能會需要在 C++11 以前的版本編譯,在這個版本以前並沒有 emplace_back()
  2. 我們不清楚建構函式(constructor)是哪種的情況

References 的連結中給出了一個清楚的說明:

std::vector<std::vector<int>> vec1, vec2;
// vec1.push_back(1000000);  // compile error 
vec2.emplace_back(1000000);
std::cout << "Vector Size = " << vec2.at(0).size() << std::endl;


Output:

Vector Size = 1000000


使用 push_back() 的時候,由於賦值會編譯錯誤,所以我們會收到編譯器的警告;然而在使用 emplace_back() 的時候,我們錯誤地建構了 1,000,000 個 vector —— 這是非常恐怖的記憶體開銷

所以,要使用 emplace_back() 優化我們的程式時,也需要注意這些事項。


References


Read More

Tags:

Leave a Reply取消回覆

Exit mobile version