管理带有预分配内存和数组的析构函数
Managing destructors with pre-allocated memory and arrays
你好,所以我正在尝试用预分配的内存创建对象和数组。例如,我有以下代码:
int * prealloc = (int*)malloc(sizeof(Test));
Test *arr = new(prealloc) Test();
其中test的定义如下:
class Test {
public:
Test() {
printf("In Constructorn");
}
~Test() {
printf("In Destructorn");
}
int val;
};
在这种情况下,如果我调用delete,它实际上会释放内存,这是坏的,b/c也许我正在使用某种类型的内存管理器,所以这肯定会导致一些问题。我在网上搜索了一下,我找到的唯一解决方案是显式调用析构函数,然后调用free:
arr->~Test();
free(arr);
还有别的方法吗?是否有一种方法可以调用delete并告诉它只调用析构函数而不释放内存?
我的第二个问题是在处理数组时,像前面的例子一样,您可以将预分配的内存传递给new:
int * prealloc2 = (int*)malloc(sizeof(Test) * 10);
Test *arr2 = new(prealloc2) Test[10];
如果我调用delete[]
,它不仅会调用数组中每个元素的析构函数,而且还会释放内存,这是我不想要的。我发现应该这样做的唯一方法是遍历数组并显式调用析构函数,然后调用free。就像常规的无数组操作符一样,有没有一种方法可以告诉操作符只调用析构函数而不释放内存?
我注意到的一件事是,数组的新操作符实际上会使用前4个字节来存储数组的大小(我只在visual studio中用32位构建测试了这一点),这将帮助我知道数组有多少元素,但仍然有一个问题。如果数组是指针数组呢?例如:
Test **arr2 = new Test*[10];
有人能帮我解决一下这些问题吗?
直接调用析构函数来销毁使用placement new创建的对象是正常的。至于其他方法,唯一明显的替代方法是使用Allocator对象(至少99%的情况下,它只是对位置new的包装,并直接调用析构函数)。
一般来说,根本不想使用new[]
。您通常希望用operator new
(或者可能是::operator new
)分配原始内存,并将其与匹配的operator delete
或::operator delete
一起释放。
在内存中使用new位置创建对象,并通过直接调用析构函数来销毁它们。
只能显式调用析构函数,因为delete也会尝试释放内存。
在你的代码中使用带有位置new的预分配内存应该是相当罕见的——一个典型的用例是当你处理直接内存映射的硬件接口时,当你想/需要在固定内存地址的顶部映射一个对象时——我通常认为这是一种代码气味。
如果您想为特定的类调整内存管理,您最好使用带有自定义分配器的STL容器,或者为特定的类重载new和delete操作符。
是的,这是唯一的方法。允许定义new
而不允许定义delete
是不对称的。[好吧,你可以做后者,但它只能在new
抛出异常时被调用(下面没有正确处理!)
您可以使用模板化的destroy
来实现相同的结果:
class Test
{
public:
Test() {
printf("In Constructorn");
}
~Test() {
printf("In Destructorn");
}
int val;
};
class Allocator
{
public:
static void* allocate(size_t amount) { return std::malloc(amount);}
static void unallocate(void* mem) { std::free(mem);}
static Allocator allocator;
};
Allocator Allocator::allocator;
inline void* operator new(size_t size, const Allocator& allocator)
{
return allocator.allocate(size);
}
template<class T>
void destroy(const Allocator& allocator, T* object)
{
object->~T();
allocator.unallocate(object);
}
int main()
{
Test* t = new (Allocator::allocator) Test();
destroy(Allocator::allocator, t);
return 0;
}
- 如何在析构函数中删除C++中动态分配的数组?
- 为什么数组中对象的析构函数在被另一个对象替换时不被调用?
- C++ 在析构函数调用之前删除的动态成员数组
- 取消分配动态分配的字符数组的析构函数
- 在C++中删除指针数组时析构函数崩溃
- 为什么我不能使用已删除或私有析构函数分配类的数组?
- 如何对动态数组中的某些对象调用析构函数
- 为什么析构函数和复制构造函数使用对象数组显示此行为
- 这是删除析构函数中的数组的正确方法吗?
- 指向数组的指针的析构函数
- 具有受保护析构函数的类数组的动态分配
- 析构函数立即调用并删除我的数组
- 为什么析构函数不释放数组内存?
- 如何在具有指向对象的指针数组的类中创建复制构造函数和析构函数,其中对象本身具有指向整数的指针数组
- 析构函数删除在 main 中声明的动态数组
- 删除类数组而不调用析构函数
- 构造函数、析构函数和指针(以及向量、数组和删除等等)
- C++析构函数删除包含动态数组作为数据成员的对象时的用法
- C++动态数组析构函数错误
- c++字符串数组析构函数