2

考虑以下代码,

#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 时,我会调用析构函数。这是否意味着调用析构函数后释放堆栈上的内存?

如果我动态请求之前在堆上分配的内存,在这种情况下我需要调用删除,但删除实际上释放了堆栈上的内存吗?

4

3 回答 3

14

普通的 new 操作符做两件事:

  1. 调用动态内存管理器来获取内存块
  2. 调用构造函数

正常的删除操作符做相反的事情

  1. 调用析构函数
  2. 调用动态内存管理器释放内存块

Placement new 只做一步:

  1. 调用构造函数

所以“位置删除”应该只做一步:

  1. 调用析构函数

您不应该像您所做的那样在放置新后调用正常删除。(原因是这样做会要求动态内存管理器删除它没有分配的块,从而导致未定义的行为)

这一行是错误的:

delete samplePtr;  // WRONG

您需要执行“放置删除”,这只是对析构函数的原始调用:

samplePtr->~sample(); // CORRECT
于 2012-03-27T11:31:25.290 回答
1

您正在做的事情(free未分配的可用内存malloc)会导致未定义的行为 - 任何事情都可能发生。与deleteing 未通过 获取的指针相同new。与deletemalloc或相反获得的指针相同。

仅仅因为它看起来“有效”并不意味着它是正确的。您不能free堆叠内存。在这种情况下,您需要直接调用析构函数是正确的。

于 2012-03-27T11:31:45.057 回答
0

这就是为什么放置 new 可能不好(实际上你应该尽可能避免它,在这种情况下,只是堆栈分配对象),你不应该delete使用内存(因为它从来没有被new首先创建,而是你需要做samplePtr->~sample();

于 2012-03-27T11:34:03.970 回答