• Class / Function / Type

      std::
    • Header file

      <>
    • Other / All

    最終更新日時(UTC):
    が更新

    履歴 編集

    function
    <vector>

    std::vector::push_back

    void push_back(const T& x);           // (1) C++03
    constexpr void push_back(const T& x); // (1) C++20
    
    void push_back(T&& x);                // (2) C++11
    constexpr void push_back(T&& x);      // (2) C++20
    

    概要

    新たな要素を末尾に追加する。

    テンプレートパラメータ制約

    • (1)
      • T*thisのコンテナに対してコピー挿入可能であること
      • Tコピー代入可能であること
    • (2)
      • T*thisのコンテナに対してムーブ挿入可能であること
      • Tムーブ代入可能であること

    効果

    • (1) : xのコピーを、末尾に追加する。
    • (2) : 一時オブジェクトxをムーブして、末尾に追加する。

    戻り値

    なし

    計算量

    償却定数時間。

    この関数を呼び出す前にsize() < capacity()であった場合、この関数の実行は定数時間で行われる。そうでない場合は、メモリ領域の再確保と、その領域への要素のコピーもしくはムーブが行われるため、線形時間で実行される。

    vectorの実装で行われるメモリ確保戦略では、再確保の際にそれら要素がぴったり収まるサイズを確保するのではなく、少し多めの1.5倍や2倍といったサイズのメモリを確保し、再確保の回数を減らしている。事前に追加する要素の数がわかっている場合にはreserve()メンバ関数で事前にその要素数分のメモリを確保し、そうでない場合にはvectorのメモリ確保戦略に任せるのがよいだろう。

    備考

    • 要素を追加した後のsize()が要素を追加する前のcapacity()よりも大きい場合は領域の再確保が生じる。領域の再確保が生じなかった場合には全てのイテレータや参照は有効である。
    • 非コピー挿入可能な要素型Tのムーブコンストラクタ以外で例外が発生した場合、副作用は発生しない。

    #include <iostream>
    #include <vector>
    #include <string>
    #include <algorithm>
    
    int main()
    {
      std::vector<std::string> v;
    
      // const&バージョン
      std::string s = "hello";
      v.push_back(s);
    
      // &&バージョン
      v.push_back(std::string("world"));
    
      std::for_each(v.begin(), v.end(), [](const std::string& x) {
        std::cout << x << std::endl;
      });
    }
    

    出力

    hello
    world
    

    参照

    • 2倍だけじゃない - Derive Your Dreams
    • それでも2倍だ - Derive Your Dreams
    • LWG Issue 2252. Strong guarantee on vector::push_back() still broken with C++11?
      • C++03では、「vectorpush_back()dequepush_back()push_front()で例外が発生した場合、副作用が発生しない」という強い保証があった。
      • C++11では、ムーブ対応のため文面が見直されたが、その際にinsert() emplace()とまとめて以下のような仕様となった:
        • 「(挿入操作において、)要素型 T のコピーコンストラクタ、ムーブコンストラクタ、代入演算子、ムーブ代入演算子、あるいはInputIteratorの操作以外で例外が発生した場合、副作用が発生しない。」
        • このため、コピーコンストラクタで例外が発生した場合が保証の範囲外となり、保証が弱まってしまっていた。
      • C++14では、上記文面を見直し、終端(dequeの場合は両端)への単一要素の追加の場合に限りC++03と等価の強い保証を提供するよう修正された。
      • それに加えて、C++14ではこの強い保証を提供する関数を、以下のように拡大した:
    • P1004R2 Making std::vector constexpr