C ++“新”内存分配

时间:2013-12-05 21:06:43

标签: c++ memory-management new-operator

我想为大量对象分配内存。然后逐一构建它们。所以我做了以下几点:

BaseClass* buf = static_cast<BaseClass*> (::operator new (sizeof(BaseClass[5])));
for (int var = 0; var < 5; ++var) {
    new (&buf[var]) BaseClass(var);
}

一切似乎都好。但是当我添加删除时:

BaseClass* buf = static_cast<BaseClass*> (::operator new (sizeof(BaseClass[5])));
for (int var = 0; var < 5; ++var) {

    new (&buf[var]) BaseClass(var);

    // ... do something

    delete &buf[var];
}

我收到了“分段错误”错误。在第二次迭代(在构造函数上)。 同时

 delete [] buf;

工作正常。

所以问题是 - 为什么会这样?

3 个答案:

答案 0 :(得分:4)

Placement new不分配内存,它只调用你给它的内存位置的构造函数。因此您无需删除单个项目。而不是

delete &buf[var];

试试这个,调用析构函数而不释放内存:

buf[var].~BaseClass();

请注意,您仍然需要在整个内存块上使用::operator delete,而不是在单个对象上。

答案 1 :(得分:4)

首先,如果您使用展示位置new,则需要明确调用析构函数

buf[var].~BaseClass();

然后你可以删除已经用新分配的东西,而&buf[0]可以工作,因为它是由贴片new返回的地址,&buf[1]尚未由内存管理器直接分配{ {1}}。你不能一个一个地释放它们。

所以你应该做类似

的事情
::operator new

答案 2 :(得分:2)

您使用delete而没有相应的new。使用placement new在先前分配的内存中构造对象不需要成对使用delete运算符。相反,placement new应与显式析构函数调用配对。由于您直接调用全局operator new函数,因此您应该将其与直接调用全局operator delete函数进行配对,而不是使用delete运算符。

然而,如果这对你所描述的内容是必要的,则没有。以下更容易:

std::vector<BaseClass> buf;
buf.reserve(5);

for (int var = 0; var < 5; ++var) {
    buf.emplace_back(var);
}

拥有此对象集合后,您可以将指针指向std::vector<BaseClass*>

std::vector<BaseClass*> buf2;
buf2.reserve(buf.size());
std::transform(std::begin(buf), std::end(buf), std::back_inserter(buf2),
               std::addressof<BaseClass>);    

请确保不要对使指针无效的原始向量执行任何操作。您可以移动它,但不要复制它然后销毁原始文件。