[英]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.