包含新案例的自定义分配器

问题描述 投票:1回答:1

我正在尝试为C ++实现一个自定义分配器,该分配器可用于任何形式的new / delete / malloc / free。我的程序如何工作,我在程序开始时分配了一个x字节的内存池并使用它们。例如,当有人写int* a= new int;时,我的程序将从可用的内存池中返回该地址并将其标记为已分配,并且该地址以及分配的大小将从内存池中删除。当有人写入delete a;时,该地址将返回到内存池,并且可以再次使用。 我的问题是我不完全了解new(placement)的工作原理以及应该如何处理,因为调用我的函数在new / 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这应该如何工作?

c++ memory-management new-operator allocation
1个回答
2
投票

普通的new做两件事:

  • 分配存储空间;和

  • 构造对象。

现在,我们想将这两个步骤分开。分配原始存储很容易,但是在C ++中,没有“本机”方式在给定地址处构造对象。因此,通过返回第一步的给定指针,new运算符被重载以达到此目的。

我们不需要相应的delete,因为我们可以手动调用析构函数。在C ++ 17中,std::destroy_at已添加到标准库中。从C ++ 20开始,std::construct_at可用于构造对象,而不是放置new:

std::construct_at(p, 4, 'a');

C++ Super-FAQ很好地说明了新的位置:

什么是“新的展示位置?为什么要使用它?

有很多新的用途。最简单的用途是放置一个对象位于内存中的特定位置。这是通过提供该位置作为指向新表达式新部分的指针参数:

#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)个字节的内存组成的数组,足以容纳Fred对象。第2行创建了一个指针place指向此内存的第一个字节(遇到C程序员将注意到这一步骤是不必要的;它只在那里使代码更明显)。第3行实际上只是调用构造函数Fred::Fred()this中的Fred指针构造函数将等于place。返回的指针f将因此等于place

ADVICE:除非必要,请不要使用这种“新放置”语法。仅当您确实关心将对象放置在内存中的特定位置。例如,当您的硬件具有内存映射的I / O计时器设备,并且您想放置Clock对象在该内存位置。

DANGER:您独自承担传递给“ placement new”运算符的指针指向内存区域的责任。足够大,并已根据您所使用的对象类型正确对齐创造。编译器和运行时系统都不做任何事情尝试检查您是否这样做正确。如果您的Fred班级需要在4字节边界上对齐,但是您提供了一个位置排列不正确,可能会给您带来严重的灾难手(如果您不知道“对齐”是什么意思,请不要使用[[please展示位置新语法)。您已被警告。

您还独自负责破坏放置的对象。这是通过显式调用析构函数来完成的:

void someCode() { char memory[sizeof(Fred)]; void* p = memory; Fred* f = new(p) Fred(); // ... f->~Fred(); // Explicitly call the destructor for the placed object }

这是您唯一显式调用析构函数的时间。
© www.soinside.com 2019 - 2024. All rights reserved.