繁体   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