使用自定义分配器调用对象构造函数/析构函数

mmu*_*phy 10 c++ memory memory-management new-operator

我一直在研究自定义分配器,我经常看到它们使用某种功能来分配内存.出于测试目的并进一步教育我自己,我试图做出一个"简单"的例子.但是,我对如何做有一个基本的了解.mallocvs中的一个主要区别new是,新的构造函数被调用.如果我想编写我自己的基本上替换的分配器new,如何在使用时调用构造函数malloc怎么办?

我理解在类上我可以重载newdelete类,所以我想问题的一个重要部分是,如何new在分配期间调用对象构造函数?同样,我对如何delete调用析构函数感兴趣.

我创建了一个示例测试代码,我希望SomeClass在分配期间调用构造函数,但我不知道如何.

#include <malloc.h>

void* SomeAllocationFunction(size_t size) {
    return malloc(size);
}

class SomeClass
{
public:
    SomeClass() {
        int con = 1000;
    }

    ~SomeClass() {
        int des = 80;
    }
};

int main(void){
    SomeClass* t = (SomeClass*)SomeAllocationFunction(sizeof(SomeClass));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

(作为一个注释,我知道我可以使用new.但是,出于学习的目的,我正在尝试创建一个不仅仅调用的自定义分配器newplacement new).

Jer*_*fin 14

实质上,当你使用像:T *t = new T;这样的新表达式时,它大致相当于:

void *temp = operator new(sizeof(T));
T *t = new(temp) T;
Run Code Online (Sandbox Code Playgroud)

因此,首先使用分配函数分配一些原始内存,然后在该内存中构造一个对象.同样,当您使用如下的删除表达式时delete t;,它大致相当于:

t->~T();
operator delete(t);
Run Code Online (Sandbox Code Playgroud)

所以,如果你重载newdelete为特定的类:

class T { 
    int data; 
public:
    // I've made these static explicitly, but they'll be static even if you don't.
    static void *operator new(size_t size) { 
        return malloc(size);
    }
    static void operator delete(void *block) { 
        free(block);
    }
};
Run Code Online (Sandbox Code Playgroud)

然后,当你使用一个新的表达式时,它将调用类' operator new来分配内存,然后调用malloc,所以T *t = new T();最终将通过分配内存malloc(同样,当你使用delete它时,它将使用operator delete,它将调用free).

至少在通常使用的术语中,分配器非常相似,除了它由容器而不是其他代码使用.它还将分配函数和删除函数封装到一个类中,因此当您将一个函数传递给容器时,您只需传递一个对象,并且分配和删除函数几乎不会出现不匹配的情况.

暂时忽略有关用于事物的名称的详细信息,标准库中的Allocator类大多数都是这样做的,所以通过稍微重命名T上面的类中的函数,你将完成大约一半的写入标准分配器.为了配置和删除,它具有rebind一些内存的功能(将内存块更改为另一种类型),创建一个到位的对象(基本上只是一个新的放置包装器)并销毁一个对象(同样,琐碎的包装器)析构函数调用).当然,它使用operator newoperator delete,而不是mallocfree像我上面使用.


bjh*_*end 8

使用新的位置,您可以将已分配的内存位置传递给新运算符.然后new将在给定位置构造对象,而不对其自身进行分配.

编辑:

这是如何实现的:

int main(void){
    // get memory
    void * mem_t = SomeAllocationFunction(sizeof(SomeClass));
    // construct instance
    SomeClass* t = new(mem_t) SomeClass;

    // more code

    // clean up instance
    t->~SomeClass();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 构造函数没有名称(与析构函数相对),因此无法直接调用它们.如果希望它占用给定的内存位置,则placement new是正确构造类实例的唯一方法. (5认同)
  • 海报说他不想打电话给新人. (2认同)
  • 我没有使用新的特别要求. (2认同)