C++分配器。我知道字符串将在内部实现中分配一个new
的块缓冲区,并在析构函数中释放它(调用delete[])。
我的问题是,当使用allocator<string>
时,它是否会免费加倍?
1.字符串析构函数第一次释放
1.指向字符串第二个释放缓冲区已被释放
另外,string和allocate(n)
的缓冲区地址是否有相同的区域?
#include <iostream>
#include <memory>
#include <string>
using namespace std;
int main(int argc, char **argv)
{
const int cnt = 10;
allocator<string> alloc;
auto p = alloc.allocate(cnt);
alloc.construct(p);
for (int i = 0; i < cnt; ++i)
{
cout << p+i << endl; // print buffer address
}
alloc.destroy(p); // will it free buffer of string?
alloc.deallocate(p, cnt); // will it free buffer of string again?
return 0;
}
3条答案
按热度按时间ugmeyewa1#
让我们从
delete
开始当你
delete
一个对象时,会发生两件事:1.调用该对象的析构函数
1.为具有
new
的此对象分配的内存将释放回堆placement new
和delete
可以使用placement
new
语法在现有内存缓冲区上构造对象:当然,对于这个例子,你可以只使用普通的
new
和delete
,但它展示了你如何将内存分配与其构造以及销毁与解除分配分开。例如,如果您管理内存池,并且在析构对象时可以将内存回收回内存池,而不是回收回堆,则此技术非常有用。
std::分配器
std::allocator
提供了上述行为-使用allocate
、construct
、destroy
和deallocate
方法将内存分配和释放与对象构造和析构分离。请注意,当析构
string
对象时,std::string
析构函数将在其内部分配上调用delete
,但在上述代码中,对象本身占用的内存仅在调用alloc.deallocate
时释放。不建议在C++17中使用
construct
和destroy
C17声明了
std::allocator
的方法construct
和destroy
不推荐使用,而C20则将它们废弃。因此,从C17开始,您要么返回到placement new
,或者更好(感谢@Evg的评论)-使用std::allocator_traits::construct(),它的优点是自C20起就是constexpr
。对于析构,在使用分配器释放内存后直接调用析构函数:Code link
对于
construct_at
和destroy_at
,上面的代码可以写为:这是最简单的一个,如果你是在C20我会推荐这个选项。
Code link
最后注意:还有一个叫做
placement delete
的东西,它不是由程序员直接调用的,而是只有在对象的构造函数抛出异常时才从placement new
中调用。所以不要被它搞混了。在不释放对象本身所占用的内存的情况下就地析构对象的方法是直接调用它的析构函数,如上所示(或者如果你在C17之前使用std::allocator,通过调用allocator destroy方法)。最后一点:如果您想知道为什么
deallocate
需要大小,请参阅:why does std::allocator::deallocate require a size?gwo2fgha2#
当你这样写的时候:
会发生两件事:
1.为
Foo
对象分配了一些堆空间。1.调用
Foo()
构造函数,this
指向新分配的空间。稍后,删除
Foo
对象:还有两件事会发生
1.调用析构函数
~Foo()
。1.为Foo示例分配的内存将释放回堆。
std::allocator
类只允许您手动执行这四个步骤中的每一个。如果你有一个
allocator<string> alloc
,你调用alloc.allocate
,然后调用alloc.construct
,这和new string()
是一样的,当你调用alloc.destroy
,然后调用alloc.deallocate
,这和删除string
指针是一样的。因此,不会有任何额外的释放。对
destroy
的调用导致string
释放它为它的缓冲区分配的任何内存,然后对deallocate
的调用释放用于string
对象本身的内存。我没有完全理解你关于区域的问题。分配给存储
string
示例的内存和string
分配给它的缓冲区的内存是不相关的。idfiyjo83#
您可以继承
std::string
来添加一些print语句,以获得更好的理解(或者您需要调试并单步执行STL容器和函数)在此处执行:
https://coliru.stacked-crooked.com/a/13302c7f0c4db07b