[英]why does returning a map.insert().second introduce unreachable memory?
[英]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.