template <class... Args>
pair<iterator, bool> emplace(Args&&... args);
概要
コンテナ内へ要素を直接構築する
テンプレートパラメータ制約
- このコンテナの要素型
value_type
が、コンテナに対して引数args
から直接構築可能であること
効果
std::forward<Args>(args)...
から構築された value_type
のオブジェクトを t
とすると、t.first
と等価なキーがコンテナに既に存在していなければ、t
をコンテナに挿入する。
なお、オブジェクト t
は、構築後にコンテナにコピー、あるいはムーブされるわけではなく、コンテナ内に直接構築される。
戻り値
std::pair
の bool
部分(second
部)は、要素が追加されたら true
、追加されなかったら(既にあったら)false
。
std::pair
の iterator
部分(first
部)は、追加された要素(bool
部分が true
の場合)、あるいは、既にあった要素(bool
部分が false
の場合)を指すイテレータ。
例外
ハッシュ関数以外から例外が投げられた場合には、挿入はされない。
計算量
平均的なケースでは定数(O(1
))だが、最悪のケースではコンテナの要素数に比例(O(size()
))。
備考
-
この関数が呼ばれた後も、当該コンテナ内の要素を指す参照は無効にはならない。
なお、規格書に明確な記載は無いが、当該コンテナ内の要素を指すポインタも無効にはならない。 -
この関数が呼ばれた後も、呼び出しの前後でこのコンテナのバケット数(
bucket_count()
の戻り値)が変わらなかった(=リハッシュが発生しなかった)場合、当該コンテナを指すイテレータは無効にはならない。
それ以外の場合は、当該コンテナを指すイテレータは無効になる可能性がある。
コンテナのバケット数が変わらない条件は、- この関数を呼び出した後の要素数が、呼び出す前のバケット数(
bucket_count()
の戻り値)×最大負荷率(max_load_factor()
の戻り値)以下である。
となっている。
なお、この条件は C++14 までは「以下」ではなく「よりも小さい」だったため、最大負荷率の定義と不整合だった。
これは規格の誤りとして C++17 で修正されたが、使用する処理系やそのバージョンによっては以前の「よりも小さい」という条件でしかイテレータの有効性を保証していない可能性があるため、注意が必要である。 - この関数を呼び出した後の要素数が、呼び出す前のバケット数(
-
C++17 で追加された
try_emplace
と異なり、この関数ではキー重複によって要素の挿入が行われなかった場合に引数が不変である(引数からのムーブが発生しない)という保証はないので、注意すること。 -
このメンバ関数は、コンテナの種類によってシグネチャが異なるため、注意が必要である。
emplace_hint
も含めた一覧を以下に示す。コンテナ シグネチャ シーケンスコンテナ template <class... Args>
iterator emplace(const_iterator, Args&&...)
連想コンテナ、非順序連想コンテナ
(同一キーの重複を許さない場合)template <class... Args>
pair<iterator, bool> emplace(Args&&...)
連想コンテナ、非順序連想コンテナ
(同一キーの重複を許す場合)template <class... Args>
iterator emplace(Args&&...)
連想コンテナ、非順序連想コンテナ template <class... Args>
iterator emplace_hint(const_iterator, Args&&...)
例
#include <iostream>
#include <unordered_map>
#include <string>
#include <complex>
#include <tuple>
#include <utility>
#include <algorithm>
// サンプルで使用する型の別名
using sc = std::pair<const std::string, std::complex<double>>;
// サンプルで使用する型の別名のための挿入演算子
std::ostream& operator<<(std::ostream& os, const sc& p)
{
return os << '{' << p.first << ',' << p.second << '}';
}
int main()
{
std::unordered_map<std::string, std::complex<double>> um;
std::cout << std::boolalpha;
auto p1 = um.emplace("e", 2.718281828);
std::cout << *p1.first << ' ' << p1.second << '\n';
auto p2 = um.emplace("pi", 3.14159265);
std::cout << *p2.first << ' ' << p2.second << '\n';
auto p3 = um.emplace("pi", 3);
std::cout << *p3.first << ' ' << p3.second << '\n';
auto p4 = um.emplace(std::piecewise_construct, std::forward_as_tuple("i"), std::forward_as_tuple(0, 1));
std::cout << *p4.first << ' ' << p4.second << '\n';
std::for_each(um.cbegin(), um.cend(), [](const decltype(um)::value_type& p) {
std::cout << p << ", ";
});
std::cout << std::endl;
}
出力
{e,(2.71828,0)} true
{pi,(3.14159,0)} true
{pi,(3.14159,0)} false
{i,(0,1)} true
{pi,(3.14159,0)}, {i,(0,1)}, {e,(2.71828,0)},
注:unordered_map
は非順序連想コンテナであるため、出力順序は無意味であることに注意
バージョン
言語
- C++11
処理系
- Clang: 3.1 ✅
- GCC: 4.7.0 ✅
- ICC: ?
- Visual C++: ?
備考
- Clang 3.3 以降は C++17 モードでなくても C++17 の条件でのリハッシュとなっている。
- GCC は 8.2.0 時点でまだ C++17 の条件でのリハッシュとなっていない。また、バージョンによってリハッシュ条件が微妙に異なるため注意。
関連項目
名前 | 説明 |
---|---|
emplace_hint |
挿入位置のヒントを使用したコンテナ内への要素の直接構築 |
try_emplace |
キーが存在しない場合のみコンテナ内への要素の直接構築 |
insert |
要素の追加 |
insert_or_assign |
要素の追加、あるいは代入 |
erase |
要素の削除 |
clear |
全要素の削除 |
swap |
内容の交換 |
bucket_count |
バケット数の取得 |
load_factor |
現在の負荷率(バケットあたりの要素数の平均)を取得 |
max_load_factor |
負荷率の最大値を取得、設定 |
rehash |
最小バケット数指定によるバケット数の調整 |
reserve |
最小要素数指定によるバケット数の調整 |