簡體   English   中英

位置 function 通過就地構造而不是通過分配向容器添加新元素是什么意思?

[英]What does it mean that the emplacement function adds a new element to a container via construction in place istead of via assignment?

Effective Modern C++的第 41 項中,Scott Meyers 提到了這種差異及其對插入效率的影響。

我對此有一些疑問,但在提出問題之前,我需要了解這兩種添加元素的方式之間的區別是什么。

考慮書中的代碼示例:

std::vector<std::string> vs;
// adding some elements to vs
vs.emplace(v.begin(), "xyzzy");

很明顯,在// adding some elements to vs之后,可能是

  • vs.capacity() == vs.size() ,或
  • vs.capacity() > vs.size()

相應地,

  • vs必須重新分配,並且 vs 中的所有預先存在的元素(那些名為vs vs[0]vs[1] ,...在重新分配發生之前)必須移動構造到新的 memory 位置(新位置的vs[1] , vs[2] , ...)
  • vs必須vs.resize(vs.size() + 1)並且所有預先存在的元素必須移動分配給下一個索引,顯然是向后處理,從最后一個元素到第一個元素。

(顯然我提到了移動操作,因為std::string提供了noexcept移動操作。如果不是這種情況,那么上面的場景略有不同,將使用復制操作。)

然而,我的問題的症結所在,就在上面的代碼之后,書上寫着(我的斜體

[…] 很少有實現會將添加的std::string構造到由vs[0]占用的 memory中。 相反,他們會將值移動分配到位。 […]

在完成房間以容納新元素之后,這兩種情況是什么?

  • 如果emplace通過移動賦值添加元素,則意味着它確實v[0] = std::string{strarg}; 其中strarg == "xyzzy" ,對嗎?
  • 但是構造v[0]占用的元素的另一種情況是什么? 這是一個new的展示位置嗎? 它會是什么樣子? 我想它應該類似於Placement new here部分的代碼塊,但我不確定在這種情況下它會是什么樣子。

有許多不同的方式來實現emplace ,並且標准對於實現必須如何做到這一點非常松懈。

給定一個指向由std::allocator_traits<allocator_type>::allocate的位置的指針,向量構造新 object 的唯一方法是使用std::allocator_traits<allocator_type>::construct 對於默認分配器,這將調用placement new。

現在,如果確實發生了重新分配,放置新元素的明顯方法是調用allocator_traits::construct(get_allocator(), ptr, std::forward<Args>(args...)) 這將等效於new (ptr) std::string("xyzzy") 但請注意,所有其他元素也通過allocator_traits::construct(get_allocator(), ptr, std::move(old_ptr))移動構造到新緩沖區。

如果沒有發生重新分配,大多數實現只會使用value_type(std::forward<Args>(args...))構造一個元素並從中移動分配(相當於v[0] = std::string("xyzzy") )。 這就是 libstdc++ 所做的。

或者,代替移動構造v[0] = std::string("xyzzy") , object 可以通過allocator_traits::destroy(&v[0])->~value_type()用於默認分配器)銷毀,然后可以通過allocator_traits::construct就地構造它。 這似乎更難實現,因為如果移動構造函數拋出,需要特別注意確保元素不會被破壞兩次,這可能就是為什么只有“少數實現”會這樣做。

順便說一句,沒有強大的異常保證,因此不一定要使用move_if_noexcept ,並且可以始終調用移動構造函數,即使移動構造函數不是noexcept

暫無
暫無

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

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