自定义分配器,包括放置新案例
Custom allocator including placement new case
我正在尝试为C++实现一个自定义分配器,该分配器适用于任何形式的new/delete/malloc/free
我的程序是如何工作的,我在程序开始时分配一个x字节的内存池并使用它们。例如,当有人写入int* a= new int;
时,我的程序将从可用的内存池中返回地址,并将其标记为已分配,该地址和已分配的大小将从内存池中删除。当有人写入delete a;
时,地址会返回到内存池中,并且可以再次使用
我的问题是,我不完全理解new(placement)
是如何工作的,以及我应该如何处理它,因为当我的函数被调用以在新的/malloc上分配内存时,我只有程序需要的内存大小作为参数,我只会返回一个可用的地址给要使用的内存。考虑以下示例
auto p = (std::string*)malloc(5 * sizeof(std::string));
void * placement = p;
new(placement) std::string(4, (char)('a'));
std::cout<< *p;
在第一行上,我的自定义分配器将从我的内存池中返回一个地址,其中有总共5* sizeof(std::string))
的可用内存,在第三行上,自定义分配器将再次分配内存,返回另一个地址。当我打印*p
时,它打印的正是我所期望的aaaa
它应该这样工作吗
一个正常的new
做两件事:
-
分配存储;和
-
构造一个对象。
现在我们要将这两个步骤分开。分配原始存储很容易,但在C++中没有在给定地址构造对象的"本机"方法。因此,通过返回第一步的给定指针,new
运算符被重载以达到此目的。
我们不需要相应的delete
,因为我们可以手动调用析构函数。在C++17中,std::destroy_at
被添加到标准库中。由于C++20,std::construct_at
可以用于构造对象,而不是放置新对象:
std::construct_at(p, 4, 'a');
C++超级常见问题解答很好地解释了放置新:
什么是"新职位"?我为什么要使用它
放置new有很多用途。最简单的用途是放置对象。这是通过提供作为指向新表达式的新部分的指针参数的位置:
#include <new> // Must #include this to use "placement new" #include "Fred.h" // Declaration of class Fred void someCode() { char memory[sizeof(Fred)]; // Line #1 void* place = memory; // Line #2 Fred* f = new(place) Fred(); // Line #3 (see "DANGER" below) // The pointers f and place will be equal // ... }
第1行创建一个
sizeof(Fred)
字节内存数组大到足以容纳CCD_ 13对象。第2行创建一个指针place
指向该内存的第一个字节(经验C程序员会注意到这个步骤是不必要的;它就在那里以使代码更加明显(。第3行本质上只是调用构造函数CCD_ 15。Fred
中的this
指针构造函数将等于place
。返回的指针f
将因此等于CCD_ 20。建议:除非迫不得已,否则不要使用此"placement-new"语法。只有当您真正关心对象放置在存储器中的特定位置。例如,当您的硬件具有内存映射的I/O计时器设备,并且要放置
Clock
对象在该存储器位置。危险:您将全权负责传递给"placement-new"操作符的指针指向的内存区域足够大,并且与您所在的对象类型正确对齐创建。编译器和运行时系统都没有试着检查一下你做得是否正确。如果您的
Fred
类需要在4字节边界上对齐,但您提供了一个位置如果没有正确对齐,您的手(如果你不知道"对齐"是什么意思,请不要使用放置新语法(。您已收到警告。您还全权负责破坏放置的对象。这是通过显式调用析构函数来实现的:
void someCode() { char memory[sizeof(Fred)]; void* p = memory; Fred* f = new(p) Fred(); // ... f->~Fred(); // Explicitly call the destructor for the placed object }
这大约是您唯一一次显式调用析构函数。
- C 和 C++ 中开关语句的案例标签的常量值,但显示不同的行为
- 为什么这个案例陈述需要一个"if else"而不仅仅是一个"if"?
- C++ switch 语句:对案例进行分组,并针对每个案例给出特定的说明
- 任意大小的 constexpr 数组是否可以用作 switch 语句中的案例?
- Python & C-C++ 扩展模块案例段故障
- 与 SDL2(以及类似案例)一起构建SDL2_image
- 自定义分配器,包括放置新案例
- 案例内部的功能
- 正在读取开关案例中的.txt文件
- 弄清楚这段代码是怎么回事(递归下降案例研究)
- C++实用程序,用于将长开关语句转换为封装开关案例阶梯的简洁函数调用
- 在任何案例之前,在 switch 语句中的使用声明是否合法?
- 案例标签值已出现错误
- 案例语句不会前进到下一个语句
- C++的研究案例.抽象类和实例
- 对两个案例标签使用相同的值与对单个案例使用多个案例标签有什么区别?
- QR码生成算法数据掩盖实现案例分析
- C .如何通过在交换机案例中再次询问用户名来找到密码
- 案例未执行
- 新设置开关案例arduino