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) :
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では、「
vector
のpush_back()
、deque
のpush_back()
とpush_front()
で例外が発生した場合、副作用が発生しない」という強い保証があった。 - C++11では、ムーブ対応のため文面が見直されたが、その際に
insert() emplace()
とまとめて以下のような仕様となった:- 「(挿入操作において、)要素型 T のコピーコンストラクタ、ムーブコンストラクタ、代入演算子、ムーブ代入演算子、あるいはInputIteratorの操作以外で例外が発生した場合、副作用が発生しない。」
- このため、コピーコンストラクタで例外が発生した場合が保証の範囲外となり、保証が弱まってしまっていた。
- C++14では、上記文面を見直し、終端(
deque
の場合は両端)への単一要素の追加の場合に限りC++03と等価の強い保証を提供するよう修正された。 - それに加えて、C++14ではこの強い保証を提供する関数を、以下のように拡大した:
vector
のpush_back()
(C++03から)vector
のemplace_back()
(C++14から)vector
の終端へ単一要素を挿入するinsert()
とemplace()
(C++14から)deque
のpush_back()
とpush_front()
(C++03から)deque
のemplace_back()
とemplace_front()
(C++14から)deque
の両端へ単一要素を挿入するinsert()
とemplace()
(C++14)
- C++03では、「
- P1004R2 Making
std::vector
constexpr