2017-04-16 67 views
3
class A { 
public: 
    explicit A(int x) {} 
}; 

vector<A> v; 
v.push_back(1); // compiler error since no implicit constructor 
v.emplace_back(1); // calls explicit constructor 

以上內容來自David Stone的video。我不明白爲什麼emplace_back調用 的顯式構造函數?我沒有看到任何在C++標準 使這個合法。只有聽完David Stone的YouTube視頻後,我才知道這件事。std :: map emplace failed with explicit constructor

現在,我嘗試與std::map一樣。

map<int, A> m; 
m.insert(pair<int, A>(1, 2)); // compiler error since no implicit constructor 
m.emplace(1, 2); // compiler error since no implicit constructor 

爲什麼emplace在這裏失敗?如果emplace_back可以調用顯式的 構造函數,那麼爲什麼不emplace也這樣做?

回答

1

m.insert(std::pair<int, A>(1, 2))編譯,我不知道爲什麼它不能爲你編譯。也許忘了-std=c++11標誌?這是因爲std::pair構造函數在將元素複製到firstsecond時顯式調用構造函數。

如果您想要置入std::map,則必須在std::pair中指定密鑰和值。您可以使用std::make_pair爲:

m.emplace(std::make_pair(1, 2)); 

這將編譯,因爲該貨幣對將在鍵/值對的地方得到構建,以及明確的構造函數將被調用。

+2

這與條件明確的構造函數有關,它正式添加在C++ 17中,但是在C++ 11之後由最新版本的GCC實現。 –

+0

我用C++ 14標誌,但我有gcc版本4.9.2。我試着用gcc 6.2,現在都是「m.insert(對(1,2))和m.emplace(1,2);」編譯。另外,對於map.emplace,我不相信有必要使用make_pair。 –

3

emplace方法通過使用placement new operator顯式調用構造函數來插入元素。在映射到映射中時,您需要單獨轉發構造鍵和值的參數。

m.emplace 
(
    ::std::piecewise_construct // special to enable forwarding 
, ::std::forward_as_tuple(1) // arguments for key constructor 
, ::std::forward_as_tuple(2) // arguments for value constructor 
); 
2

emplace功能調用你的構造如在http://eel.is/c++draft/container.requirements.general#15.5

T在標準中描述的是EmplaceConstructibleXargs,零個或多個參數args,意味着以下表達式是公形成:

allocator_traits<A>::construct(m, p, args)

這意味着它最終歸結於您的分配器。望着什麼調用手段的參考,我們可以檢查http://en.cppreference.com/w/cpp/memory/allocator_traits/construct

我們看到,如果分配不具有構造成員函數,或者如果它是std::allocator,則調用等效於

::new (static_cast<void*>(p)) T(std::forward<Args>(args)...)

對於std::map<int, A>,表達式中的Tstd::pair<int const, A>args...1, 2。因此,要知道您對emplace的呼叫是否格式良好,我們只需確定是否對std::pair<int const, A>(1, 2)的呼叫有效。因此,我們看看std::pair的文檔:http://en.cppreference.com/w/cpp/utility/pair/pair

問題的構造函數被列爲/*EXPLICIT*/ constexpr pair(const T1& x, const T2& y);(假設C++ 17)。換句話說,就像調用一個普通函數,它接受int const &作爲第一個參數,而A const &作爲第二個參數。 A只能從int明確構建,所以您的電話不合格。 emplace調用只會將您從explicit保存在您直接構建的任何對象上,在本例中僅爲std::pair,而不是該類型的任何參數。