C++ map(STL map)構造元素(emplace和emplace_hint函數)詳解

2020-07-16 10:04:27
map 容器的成員函數 emplace() 可以在適當的位置直接構造新元素,從而避免複製和移動操作。它的引數通常是構造元素,也就是 pair<const K,T> 物件所需要的。只有當容器中現有元素的鍵與這個元素的鍵不同時,才會構造這個元素。下面是一個範例:
std::map<Name, size_t> people;
auto pr = people.emplace (Name { "Dan","Druff"},77);
這個 map 包含的是 Name 型別(前面章節中定義過)的鍵。物件的型別是 size_t,所以 map 包含的是 pair<const Name,size_t> 型別的元素。emplace() 的第一個引數是一個 Name 物件,它同時也是元素的鍵,第二個引數是 size_t 型別的值,函數會用這些引數呼叫 pair<const Name,size_t> 的建構函式以在適當的位置生成元素。如果用 emplace() 的引數構造 pair 物件,那麼會呼叫 pair<const Name,size_t> 物件的移動建構函式。

成員函數 emplace() 和 insert() 返回的 pair 物件提供的指示相同。pair 的成員變數 first 是一個指向插入元素或阻止插入的元素的疊代器;成員變數 second 是個布林值,如果元素插入成功,second 就為 true。

map 的成員函數 emplace_hint() 和 emplace() 生成元素的方式在本質上是一樣的,除了必須為前者提供一個指示元素生成位置的疊代器,作為 emplace_hint() 的第一個引數。例如:
std::map<Name, size_t> people;
auto pr = people.emplace(Name{"Dan","Druff"}, 77);
auto iter = people.emplace_hint (pr.first, Name {"Cal","Cutta"}, 62);
這裡,emplace_hint() 呼叫使用一個疊代器作為指示符,指向先前 emplace() 呼叫返回的 pair 物件。如果容器使用這個提示符,那麼新元素會在這個指示符表示的位置之前生成,並盡可能靠近這個位置。提示符後面的引數用來構造新元素。需要注意的是,它和 emplace() 的返回值是不一樣的。emplace_hint() 的返回值不是一個 pair 物件,如果新元素被插入,它返回的是指向新元素的疊代器;如果沒有插入,返回的是和這個鍵匹配的現有元素的疊代器,擁有相同的 key 值,如果不是現有元素的話。沒有提示可以直接判斷是否生成了新元素。唯一的方法是,用 size() 成員函數來獲取 map 中對應元素的數量來檢查 map 元素增加的數量。例如:
auto pr = people.emplace(Name{"Dan", "Druff"}, 77);
auto count = people.size ();
auto iter = people.emplace_hint (pr.first, Name {"Cal", "Cutta"}, 62);
if(count < people.size ()) std::cout <<"Success!n";
只有當呼叫 emplace_hint() 後,people 中的元素增加時,才會顯示這些資訊。