[英]Do I need a deleter for shared_ptr to free memory allocated by an allocator?
[英]Can I use an allocator object to free memory allocated by another allocator?
據我所知,庫引入了std::allocator
來分配未初始化的未構造內存塊。 所以:
std::allocator<int> a;
auto ptr = a.allocate(100);
auto e = ptr;
while (e != ptr + 5)
a.construct(e++, 0);
for (auto tmp = ptr; tmp != e; )
std::cout << *tmp++ << ", ";
std::cout << std::endl;
std::allocator<int> a2;
std::allocator<int> a3 = a;
for (auto tmp = ptr; tmp != e; )
a.destroy(tmp++);
//for (auto tmp = ptr; tmp != e; )
// a2.destroy(tmp++); // is it UB using a2 here to destroy elements?
//for (auto tmp = ptr; tmp != e; )
// a3.destroy(tmp++); // is it UB also?
a.deallocate(ptr, 100); // ok
//a2.deallocate(ptr, 100); // UB or OK?
//a3.deallocate(ptr, 100); // UB or ok?
我不確定的是,使用另一個分配器a2
、 a3
對象(其中一個)來釋放(解除分配)由a
分配的內存是否是未定義行為?
如果可以的話,為什么像std::vector
這樣的類有一個分配器對象,而不僅僅是創建一個臨時對象來分配/釋放內存?
請澄清以上問題。
我對標准的閱讀說這是未定義的行為,除非分配器比較相等。 表 34:Cpp17Allocator 要求 [tab:cpp17.allocator]狀態
a.deallocate(p,n)
那
要求:
p
應是先前對allocate
調用返回的值,該值未被中間調用對deallocate
無效。n
應匹配傳遞給allocate
以獲得此內存的值。
其中a
是分配器類型的左值。 由於allocate
是一個成員函數,我將引用文本中allocate
的使用解釋為a.allocate
,這意味着您需要相同或相等的對象來釋放分配的內容。
這當然意味着像vector
這樣的東西在需要時不能臨時創建,並且需要將分配器保留為成員。
您可以在此處閱讀有關分配器的規范: https : //en.cppreference.com/w/cpp/named_req/Allocator 。 它們在不同的標准版本中略有變化,但我會寫關於 C++17 和 20 的版本。
當您使用分配器a1
分配內存時,如果a1 == a2
,它只能由不同的分配器a2
釋放。引用標准:
a1 == a2
僅當從每個分配的存儲可以通過另一個解除分配時才返回true
。
std::allocator<T>
通常實現為沒有狀態的空類型。 std::allocator<T>::is_always_equal::value
為true
,所以所有std::allocator<T>
對象都相等。 因此,兩種解除分配都得到了很好的定義。
如果它是一個有狀態的分配器,在AllocatorT a3 = a1
, a1 == a3
應該是true
,所以你可以安全地釋放它。 AllocatorT a2;
default 構造它,並且a2 == a1
可能不是真的,所以你不能用a2
解除分配。
在 C++17 中,你也可以做AllocatorT a3 = std::move(a1);
. 這意味着您不能再使用a1
解除分配(除非移動后a1 == a3
),而只能使用a3
。 這在 C++20 中已更改,因此您只能復制分配器。
目前,大多數容器實現都包含一個從分配器繼承的對象,因此如果它是空的,則使用空基優化,這樣它就不會占用任何額外的字節。 因此,即使所有對象始終相同,使用 0 個額外字節來存儲分配器也沒有什么壞處(如果它是有狀態的,則無論如何都需要存儲一個對象以解除分配)。 在 C++20 中,這可能會使用[[no_unique_address]]
屬性來實現,以獲得相同的效果。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.