简体   繁体   English

我可以使用分配器对象来释放另一个分配器分配的内存吗?

[英]Can I use an allocator object to free memory allocated by another allocator?

As far as I know, std::allocator is introduced by the library to allocate uninitialized unconstructed blocks of memory.据我所知,库引入了std::allocator来分配未初始化的未构造内存块。 So:所以:

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?
  • What I am not sure about is whether using another allocator a2 , a3 objects (one of them) to free (deallocate) memory allocated by a is Undefined Behavior?我不确定的是,使用另一个分配器a2a3对象(其中一个)来释放(解除分配)由a分配的内存是否是未定义行为?

  • If it is OK why classes like std::vector has an allocator object and not just create a temporary one to alloc/dealloc memory?如果可以的话,为什么像std::vector这样的类有一个分配器对象,而不仅仅是创建一个临时对象来分配/释放内存?

Please clarify the questions above.请澄清以上问题。

My reading of the standard says this is undefined behavior, unless the allocators compare equal.我对标准的阅读说这是未定义的行为,除非分配器比较相等。 Table 34: Cpp17Allocator requirements [tab:cpp17.allocator] states for 表 34:Cpp17Allocator 要求 [tab:cpp17.allocator]状态

a.deallocate(p,n)

that

Requires: p shall be a value returned by an earlier call to allocate that has not been invalidated by an intervening call to deallocate .要求: p应是先前对allocate调用返回的值,该值未被中间调用对deallocate无效。 n shall match the value passed to allocate to obtain this memory. n应匹配传递给allocate以获得此内存的值。

Where a is an lvalue of the allocator type.其中a是分配器类型的左值。 Since allocate is a member function I interpret the use of allocate in the quoted text to mean a.allocate which would mean you need the same or equal object to deallocate what was allocated.由于allocate是一个成员函数,我将引用文本中allocate的使用解释为a.allocate ,这意味着您需要相同或相等的对象来释放分配的内容。


This of course means that something like vector couldn't make a temporary when it needed and would need to keep the allocator as a member.这当然意味着像vector这样的东西在需要时不能临时创建,并且需要将分配器保留为成员。

You can read about the specification for allocators here: https://en.cppreference.com/w/cpp/named_req/Allocator .您可以在此处阅读有关分配器的规范: https : //en.cppreference.com/w/cpp/named_req/Allocator They have changed a bit in different standard versions, but I will write about the C++17 and 20 renditions.它们在不同的标准版本中略有变化,但我会写关于 C++17 和 20 的版本。

When you allocate memory with an allocator a1 , it can only be deallocated by a different allocator a2 if a1 == a2 .当您使用分配器a1分配内存时,如果a1 == a2 ,它只能由不同的分配器a2释放。Quote from the standard :引用标准

a1 == a2
returns true only if storage allocated from each can be deallocated via the other.仅当从每个分配的存储可以通过另一个解除分配时才返回true

std::allocator<T> is usually implemented as an empty type with no state. std::allocator<T>通常实现为没有状态的空类型。 std::allocator<T>::is_always_equal::value is true , so all std::allocator<T> objects are equal. std::allocator<T>::is_always_equal::valuetrue ,所以所有std::allocator<T>对象都相等。 Thus, both deallocations are well defined.因此,两种解除分配都得到了很好的定义。

If it was a stateful allocator, after AllocatorT a3 = a1 , a1 == a3 should be true , so you are safe to deallocate with it.如果它是一个有状态的分配器,在AllocatorT a3 = a1a1 == a3应该是true ,所以你可以安全地释放它。 AllocatorT a2; default constructs it, and a2 == a1 is probably not true, so you can't deallocate with a2 . default 构造它,并且a2 == a1可能不是真的,所以你不能用a2解除分配。

In C++17, you could also do AllocatorT a3 = std::move(a1);在 C++17 中,你也可以做AllocatorT a3 = std::move(a1); . . This means that you could no longer deallocate with a1 (Unless a1 == a3 after the move), but only with a3 .这意味着您不能再使用a1解除分配(除非移动后a1 == a3 ),而只能使用a3 This was changed in C++20, so you can only copy allocators.这在 C++20 中已更改,因此您只能复制分配器。

Currently, most container implementations contain an object that inherits from the allocator so that if it is empty, empty base optimisation is used so that it doesn't take any extra bytes.目前,大多数容器实现都包含一个从分配器继承的对象,因此如果它是空的,则使用空基优化,这样它就不会占用任何额外的字节。 So even if all objects are always the same, it doesn't hurt to use 0 extra bytes to store an allocator (And if it is stateful, an object needs to be stored anyway to deallocate).因此,即使所有对象始终相同,使用 0 个额外字节来存储分配器也没有什么坏处(如果它是有状态的,则无论如何都需要存储一个对象以解除分配)。 In C++20, this will probably be implemented with the [[no_unique_address]] attribute for the same effect.在 C++20 中,这可能会使用[[no_unique_address]]属性来实现,以获得相同的效果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我是否需要一个shared_ptr删除器来释放分配器分配的内存? - Do I need a deleter for shared_ptr to free memory allocated by an allocator? 使用由不同分配器分配的内存 - Using Memory Allocated by Different Allocator 是否存在不会隐式释放内存的STL分配器? - Is there an STL Allocator that will not implicitly free memory? 我是否应该在使用多态分配器分配的 object 上调用“删除” - Should I call `delete` on object allocated using polymorphic allocator 自定义堆分配器 - 分配的对象必须指向分配器? - Custom heap allocator - the allocated object must point back to allocator? 如何在std :: set中使用分配器? - How can I use an allocator with std::set? 如何对分层分配的类使用分配器 - How to use an allocator for a hierarchically allocated class 我可以使用任何T类作为分配器类型吗,只要std :: allocator_traits <T> 是专业的吗? - Can I use any class T as an allocator type as long as std::allocator_traits<T> is specialized? 将内存池分配器耦合到托管已分配实例的各种内存池 - Coupling memory pool allocator to various memory pools hosting the allocated instances 我可以使用为某种类型指定的分配器在C ++中分配另一种类型的对象吗? - Can I use allocator specified for some type to allocate objects of another type in C++?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM