簡體   English   中英

為什么std :: insert需要CopyConstructibility?

[英]Why does std::insert require CopyConstructibility?

為什么此代碼不起作用? 對於std :: map的insert方法,文檔中沒有關於CopyConstructibility的內容: http ://en.cppreference.com/w/cpp/container/map/insert

我可以構造std :: pair,第二個元素是我的non_copyable類,但是即使insert方法的第一個重載采用const value_type&,也無法將其插入到map中,所以應該可以正常工作。

有人可以幫助我了解為什么std :: map需要此CopyConstructibility嗎?

#include <utility>
#include <map>

struct non_copyable {
    non_copyable(){}

private:
    non_copyable(const non_copyable&);
};

int main() {
    std::pair<int, non_copyable> p; // this works!

    std::map<int, non_copyable> m;
    m.insert(std::pair<int, non_copyable>()); // this does NOT work
}

示例: https//wandbox.org/permlink/r3H6CqehfqnHPXDL

...即使insert方法的第一個重載采用const value_type& ,所以也可以正常工作。

不,實際上,在這種情況下,正確的過載解決方案候選對象是:

m.insert(std::pair<int, non_copyable>());

這是重載的成員函數:

template< class P >
std::pair<iterator,bool> insert( P&& value );

現在, 此頁面描述了為什么它不起作用:

...僅在std::is_constructible<value_type, P&&>::value == true參與重載解析。

您的non_copyable不可構造:

using M = std::map<int, non_copyable>;
using P = std::pair<int, non_copyable>;
std::is_constructible<M::value_type, P&&>::value; // false

因為沒有可用的構造函數,包括由編譯器生成的默認隱式move構造函數。

non_copyable甚至禁用其默認的隱式move構造函數的原因是,由於具有用戶定義的副本構造函數,如文檔所述

如果沒有為類類型(struct,class或union)提供用戶定義的move構造函數,則以下所有條件均成立:

沒有用戶聲明的副本構造函數

沒有用戶聲明的副本分配運算符

沒有用戶聲明的移動分配運算符

沒有用戶聲明的析構函數

現在給non_copyable一個move構造函數成為您的責任:

struct non_copyable {
    non_copyable(){}
    non_copyable(non_copyable &&) = default;

private:
    non_copyable(const non_copyable&);
};

您可能會感興趣,為什么您根本不需要制作任何副本,因此即使您可以在地圖內部直接構造(成對)對,也要提供可構造副本的類型。

這是因為要提供所需的性能,通常將std :: map的內部表示形式實現為平衡的二進制搜索樹(最終作為具有相似性能特征的另一個數據結構),這需要存儲元素的某些特定順序。 因此,在添加或刪除某些元素之后,該順序可能會中斷,並且為了保持其正確性,有時需要存儲的元素進行內部移動。

暫無
暫無

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

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