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

C++ 我可以使用分配器对象释放由另一个分配器分配的内存吗?,c++,allocator,C++,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 &l

据我所知,库引入了
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?
std::分配器a;
自动ptr=a.分配(100);
自动e=ptr;
而(e!=ptr+5)
a、 构造(e++,0);
对于(自动tmp=ptr;tmp!=e;)

我对标准的理解是这是未定义的行为,除非分配器比较相等。州

Requires:
p
应是先前调用
allocate
返回的值,该值未被中间调用
deallocate
无效<代码>n
应与传递给
分配
的值匹配,以获得该内存

其中
a
是分配器类型的左值。由于
allocate
是一个成员函数,我将引用文本中
allocate
的用法解释为
a.allocate
,这意味着您需要相同或相等的对象来取消分配所分配的内容



当然,这意味着类似于
vector
的东西在需要时无法创建临时的,并且需要将分配器作为成员保留。

您可以在此处阅读有关分配器规范的内容:。它们在不同的标准版本中有一些变化,但我将介绍C++17和20的格式副本

当您使用分配器
a1
分配内存时,只有在
a1==a2
的情况下,才能由其他分配器
a2
释放内存:

a1==a2

仅当从每个存储分配的存储可以通过另一个释放时,才返回
true

std::allocator
通常实现为无状态的空类型。是
true
,因此所有
std::allocator
对象都是相等的。因此,这两种解除分配都有很好的定义

如果它是一个有状态分配器,则在
allocatortA3=a1
之后,
a1==a3
应该是
true
,这样您就可以安全地解除分配它<代码>分配端口a2默认值构造它,并且
a2==a1
可能不是真的,因此您无法取消分配
a2

在C++17中,还可以执行
allocortA3=std::move(a1)。这意味着您不能再解除分配
a1
(除非移动后
a1==a3
),而只能解除分配
a3
。这是在C++20中更改的,因此您只能复制分配器


目前,大多数容器实现都包含一个从分配器继承的对象,因此,如果该对象为空,则会使用该对象,这样就不会占用任何额外的字节。因此,即使所有对象总是相同的,使用0个额外字节来存储分配器也无妨(如果它是有状态的,则无论如何都需要存储一个对象才能解除分配)。在C++20中,这可能会使用属性实现,以获得相同的效果。

@walnut:这是离题的。考虑一下我评论这些行,只让一个分配器工作。“NaNaulver:是的。内森。我想知道我是否可以使用
a2
a3
来释放分配器
a
分配和构造的内存?@NathanOliver:哈哈,你怎么能发现这个错误?这是让你的第二个问题对我有意义的唯一方法;)@纳萨诺利弗:是啊,这太迂腐了。你这个男人<代码>标准::分配器
实例总是比较相等,请参阅
a.deallocate(p,n)