问题
Consider the following code,
#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();
}
Output:
Inside New
0x22ff38
Constructing Object
0x22ff38
Destructing Object
Inside Delete
Here, I am dynamically requesting a memory that's already allocated on stack. I read that i need to call the destructor explicitly once i am done. But when i try and call delete for the memory allocated on stack i get a call to destructor. Does that mean that memory on stack is freed after destructor is called?
If i dynamically request for memory that's allocated on heap earlier, in that case i need to call delete, but does delete actually free memory on stack?
回答1:
The normal new operator does two things:
- Calls dynamic memory manager to get chunk of memory
- Calls constructor
The normal delete operator does the reverse
- Calls destructor
- Calls dynamic memory manager to free chunk of memory
Placement new only does one step:
- Calls constructor
So "placement delete" should only do one step:
- Calls destructor
You should not call normal delete after placement new, as you have done. (The reason is that doing so would ask the dynamic memory manager to delete a block it did not allocate, resulting in undefined behaviour)
This line is wrong:
delete samplePtr; // WRONG
You need to do "placement delete" which is just a raw call the descructor:
samplePtr->~sample(); // CORRECT
回答2:
What you're doing (free memory with free
that was not allocated by malloc
) causes undefined behavior - anything could happen. Same with delete
ing a pointer that was not obtained via new
. Same with delete
ing a pointer obtained from malloc
or the opposite.
Just because it appears to "work" doesn't mean it is correct. You must not free
stack memory. You are correct that you need to call the destructor directly in this case.
回答3:
This is why placement new can be bad (in fact you should avoid it where possible, in this case, just stack allocate the object), you shouldn't delete
the memory (because it was never created by new
in the first place, rather, you need to do samplePtr->~sample();
来源:https://stackoverflow.com/questions/9888692/freeing-memory-allocated-from-placement-new