考虑以下代码,
#include "iostream"
#include "conio.h"
using namespace std;
class sample
{
private:
int i;
public:
sample(int ii=0) : i(ii){
cout<<"Constructing Object"<<endl;
}
~sample() { cout<<"Destructing Object"<<endl; }
void* operator new(size_t nSize, void* loc){
cout <<"Inside new"<<endl;
cout <<loc<<endl;
return loc;
}
void operator delete(void* ptr){
cout <<"Inside delete"<<endl;
free(ptr);
}
};
int main()
{
int intArr[2];
sample* samplePtr = new(intArr) sample(5);
cout <<samplePtr<<endl;
delete samplePtr;
// samplePtr->sample::~sample();
getch();
}
输出:
Inside New
0x22ff38
Constructing Object
0x22ff38
Destructing Object
Inside Delete
在这里,我动态请求已经在堆栈上分配的内存。我读过,一旦完成,我需要明确地调用析构函数。但是当我尝试为堆栈上分配的内存调用delete时,我会调用析构函数。这是否意味着在调用析构函数后释放堆栈上的内存?
如果我动态请求先前在堆上分配的内存,那么我需要调用delete,但是实际上是否删除堆栈上的空闲内存?
答案 0 :(得分:14)
普通的新操作符有两件事:
普通删除操作符执行反向
Placement new只做一步:
所以“放置删除”应该只做一步:
在完成新位置后,您不应该调用正常删除操作。 (原因是这样做会要求动态内存管理器删除它没有分配的块,导致未定义的行为)
这一行错了:
delete samplePtr; // WRONG
您需要执行“placement delete”,这只是一个原始调用descructor:
samplePtr->~sample(); // CORRECT
答案 1 :(得分:1)
你在做什么(free
的空闲内存未被malloc
分配)导致未定义的行为 - 任何事情都可能发生。与delete
指针无法通过new
获得相同。与从delete
获得的指针malloc
相同。
仅仅因为看起来“工作”并不意味着它是正确的。你不能free
堆叠内存。在这种情况下,你需要直接调用析构函数。
答案 2 :(得分:0)
这就是为什么放置new可能坏(实际上你应该尽可能避免它,在这种情况下,只是堆栈分配对象),你不应该delete
内存(因为它始终不是由new
创建的,而是您需要samplePtr->~sample();