emplace與insert的區別

2021-10-05 12:19:57 字數 2444 閱讀 1968

emplace與insert的區別(c++11)

**時習之

c++11中大部分的容器對於新增元素除了傳統的 insert 或者 pusb_back/push_front 之外都提供乙個新的函式叫做 emplace。 比如如果你想要向 std::vector 的末尾新增乙個資料,你可以:

std::vector nums;

nums.push_back(1);

你也可以使用:

std::vector nums;

nums.empace_back(1);

避免不必要的臨時物件的產生

emplace 最大的作用是避免產生不必要的臨時變數,因為它可以完成 in place 的構造,舉個例子:

struct foo ;

std::vector v;

v.emplace(someiterator, 42, 3.1416); // 沒有臨時變數產生

v.insert(someiterator, foo(42, 3.1416)); // 需要產生乙個臨時變數

v.insert(someiterator, ); // 需要產生乙個臨時變數

這是 emplaceemplace 和 insertinsert 最大的區別點。emplaceemplace 的語法看起來不可思議,在上 面的例子中後面兩個引數自動用來構造 vector 內部的 foo 物件。做到這一點主要 使用了 c++11 的兩個新特性 變參模板變參模板 和 完美**完美**。」變參模板」使得 emplace 可以接受任意引數,這樣就可以適用於任意物件的構建。

」完美**」使得接收下來的引數 能夠原樣的傳遞給物件的建構函式,這帶來另乙個方便性就是即使是建構函式宣告為 explicitexplicit 它還是可以正常工作,因為它不存在臨時變數和隱式轉換。

struct bar

explicit bar(int a, double b) {}

};int main(void)

); // 無法進行隱式轉換

bv.push_back(bar(1, 2.0)); // 顯示構造臨時變數

bv.emplace_back(1, 2.0); // 沒有臨時變數

return 0;}

map 的特殊情況

mapmap 型別的 emplaceemplace 處理比較特殊,因為和其他的容器不同,map 的 emplace 函式把它接收到的所有的引數都**給 pairpair 的建構函式。對於乙個 pairpair 來說,它既需要構造它的 keykey 又需要構造它的 valuevalue。如果我們按照普通的 的語法使用變參模板,我們無法區分哪些引數用來構造 keykey, 哪些用來構造 valuevalue。 比如下面的**:

mapscp;

scp.emplace(「hello」, 1, 2); // 無法區分哪個引數用來構造 key 哪些用來構造 value

// string s(「hello」, 1), complex cpx(2) ???

// string s(「hello」), complex cpx(1, 2) ???

所以我們需要一種方式既可以接受異構變長引數,又可以區分 key 和 value,解決 方式是使用 c++11 中提供的 tuple。

pairscp(make_tuple(「hello」), make_tuple(1, 2));

然後這種方式是有問題的,因為這裡有歧義,第乙個 tuple 會被當成是 key,第二 個tuple會被當成 value。最終的結果是型別不匹配而導致物件建立失敗,為了解決 這個問題,c++11 設計了 piecewise_construct_t 這個型別用於解決這種歧義,它 是乙個空類,存在的唯一目的就是解決這種歧義,全域性變數 std::piecewise_construct 就是該型別的乙個變數。所以最終的解決方式如下:

pairscp(piecewise_construct,

make_tuple(「hello」),

make_tuple(1, 2));

當然因為 map 的 emplace 把引數原樣**給 pair 的構造,所以你需要使用同樣 的語法來完成 emplace 的呼叫,當然你可以使用 forward_as_tuple 替代 make_tuple,該函式會幫你構造乙個 tuple 並**給 pair 構造。

mapscp;

scp.emplace(piecewise_construct,

forward_as_tuple(「hello」),

forward_as_tuple(1, 2));

所以對於 map 來說你雖然避免了臨時變數的構造,但是你卻需要構建兩個 tuple 。 這種 traedoff 是否值得需要**編寫者自己考慮,從方便性和**優雅性上來說:

scp.insert(});

這種寫法都要勝過前面這個 emplace 版本。所以個人認為對於臨時變數構建代價不是 很大的物件(比如基礎型別)推薦使用 insert 而不是 emplace。

分類: c++

insert 與select的結合使用

常用的三種方式 1 select into table2 from table1 這種執行方式 首先是建立table2,然後將table1的內容複製過去。2 insert into table2 fld1,fld2 select fld1,aaa from table1 這種執行方式 從table1...

INSERT語句的速度

mysql 5.5中文參考手冊 文件insert語句的速度 插入乙個記錄需要的時間由下列因素組成,其中的數字表示大約比例 這不考慮開啟表的初始化開銷,每個併發執行的查詢開啟。表的大小以logn b樹 的速度減慢索引的插入。加快插入的一些方法 如果同時從同乙個客戶端插入很多行,使用含多個value的i...

insert函式的修改,

我們來看一下當中的第2個圓圈,為什麼使用size來相加呢?我們知道一開始我們定義的初始空間為init size 我們想一下啊,如果是第1次進行空間的增加,那麼我們使用init來進行相加是可以的,但是當第2次想加我們再想開闢空間的時候,還使用初始空間大小,加上我們所要開闢的空間大小是不可以的,因為第1...