簡體   English   中英

為什么map.insert()方法會兩次調用復制構造函數?

[英]Why does the map.insert() method invoke the copy constructor twice?

我正在創建自定義類Node ,以便使用map<int,Node>容器實現二叉樹: map<int,Node>int鍵是Node對象的標識符。 在類Node我必須實現一個復制構造函數。

在地圖上插入Node對象時,我注意到Node的復制構造函數被調用了兩次。 為什么?

cout << "node2" << endl;
Node node2;
node2.set_depth(2);
node2.make_it_branch(3,4);

cout << "map" << endl;
map<int,Node> mapping;
cout << "toInsert" << endl;
pair<int,Node> toInsert = pair<int,Node>(2,node2);
cout << "insert" << endl;
mapping.insert(toInsert);

運行上面的代碼,輸出如下:

node2
--- Node()
map
toInsert
--- Node(const Node& orig)
insert
--- Node(const Node& orig)   // Why does the copy constructor be invoked twice?
--- Node(const Node& orig)   // ------------------------------------------------
--- ~Node()
--- ~Node()
--- ~Node()
--- ~Node()

很可能是因為地圖的值類型是pair<int const, Node> ,而不是pair<int, Node> :在地圖中,鍵是常量

由於insert()接受一pair<int const, Node> const&並且您提供了pair<int, Node> ,以執行轉換,必須構造一個臨時值,從中可以依次復制構造映射中的值。

要驗證它,請更改此行:

pair<int, Node> toInsert = pair<int, Node>(2, node2);

進入這一行:

pair<int const, Node> toInsert = pair<int const, Node>(2, node2);

你應該看到對復制構造函數的額外調用消失了。

還要記住,標准庫容器的具體實現不需要執行特定數量的副本:實現可能會有所不同,不同的優化級別也可能會使事情變得不同。

您正在使用pair<int,Node> insert方法采用的類型是map<K,V>::value_type ,它定義為pair<const K,V> 編譯器必須插入另一個副本才能在這兩種類型之間進行轉換。

嘗試使用map<int,Node>::value_type而不是pair<int,Node> 最好使用類本身定義的類型,而不是從頭開始重新創建它們。

您也可以通過寫作來避免您的第一份副本。

map<int,Node>::value_type toInsert(2,node2);

代替

map<int,Node>::value_type toInsert = map<int,Node>::value_type(2,node2);

執行以下操作時:

toInsert = pair<int, Node>(2, node2);

您正在將node2傳遞給pair對象的構造函數。 即使您通過引用傳遞,概念上您將綁定在一起,這意味着pair對象正在制作node2對象的副本。 復制#1。

將此pair對象傳遞給insert函數時:

mapping.insert(toInsert);

..是的,你通過引用傳遞,但容器不知道引用的對象( toInsert )的生命周期。 所以它使它自己的副本存儲在容器中。 復制#2。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM