C++でvectorに要素を追加するときのreserveとemplace_back

std::vector に要素を追加するとき、最初に見ておきたいのが reserve() です。

要素数がある程度分かっているなら、先に容量を確保しておくと再確保を減らせます。

reserveする理由

#include <vector>

std::vector<int> values;
values.reserve(1000);

for (int i = 0; i < 1000; ++i) {
    values.push_back(i);
}

reserve() はサイズを増やすわけではありません。

容量だけを確保します。

std::vector<int> values;
values.reserve(1000);

// values.size() は 0
// values.capacity() は 1000 以上

resize() と混同しやすいですが、役割が違います。

関数 役割
reserve() 容量を確保する
resize() 要素数を変更する

push_backとemplace_back

push_back() は、作った値をvectorに追加します。

std::vector<std::string> names;

std::string name = "alice";
names.push_back(name);

emplace_back() は、vectorの中で直接構築します。

std::vector<std::string> names;
names.emplace_back("alice");

一時オブジェクトを避けたい場合は emplace_back() が合います。

ただし、何でも emplace_back() にすればよいわけではありません。すでに値があるなら push_back() の方が読みやすいこともあります。

unique_ptrを追加する場合

std::unique_ptr はコピーできないので、push_back() する場合は std::move が必要です。

std::vector<std::unique_ptr<int>> values;

auto value = std::make_unique<int>(1);
values.push_back(std::move(value));

直接作るなら emplace_back() でも書けます。

values.emplace_back(std::make_unique<int>(1));

std::move については C++でstd::moveを使うときに気をつけること に分けています。

まとめ

std::vector に大量追加するなら、まず容量を見ます。

  • 要素数が分かるなら reserve()
  • reserve() はサイズを増やさない
  • 既存の値を追加するなら push_back()
  • その場で構築するなら emplace_back()
  • unique_ptr を移すなら std::move

性能目的で複雑にする前に、まず reserve() で再確保を減らすだけでも十分効くことがあります。

関連記事