簡體   English   中英

我可以使用分配器對象來釋放另一個分配器分配的內存嗎?

[英]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?
  • 我不確定的是,使用另一個分配器a2a3對象(其中一個)來釋放(解除分配)由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::valuetrue ,所以所有std::allocator<T>對象都相等。 因此,兩種解除分配都得到了很好的定義。

如果它是一個有狀態的分配器,在AllocatorT a3 = a1a1 == 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.

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