释放从新位置分配的内存

时间:2012-03-27 11:27:11

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

考虑以下代码,

#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,但是实际上是否删除堆栈上的空闲内存?

3 个答案:

答案 0 :(得分:14)

普通的新操作符有两件事:

  1. 调用动态内存管理器以获取大块内存
  2. 调用构造函数
  3. 普通删除操作符执行反向

    1. 调用析构函数
    2. 调用动态内存管理器以释放大量内存
    3. Placement new只做一步:

      1. 调用构造函数
      2. 所以“放置删除”应该只做一步:

        1. 调用析构函数
        2. 在完成新位置后,您不应该调用正常删除操作。 (原因是这样做会要求动态内存管理器删除它没有分配的块,导致未定义的行为)

          这一行错了:

          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();