C++ 释放从新位置分配的内存

C++ 释放从新位置分配的内存,c++,memory-management,placement-new,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"

考虑以下代码

#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();
}
这里,我动态地请求已经在堆栈上分配的内存。我读到我需要在完成后显式调用析构函数。但当我尝试调用堆栈上分配的内存的delete时,我得到了对析构函数的调用。这是否意味着调用析构函数后堆栈上的内存将被释放


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

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

  • 调用动态内存管理器以获取内存块
  • 调用构造函数
  • 正常的delete操作符执行相反的操作

  • 调用析构函数
  • 调用动态内存管理器以释放内存块
  • “新放置”仅执行一个步骤:

  • 调用构造函数
  • 因此,“位置删除”只应执行一个步骤:

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

    这一行是错误的:

    delete samplePtr;  // WRONG
    
    您需要执行“placement delete”,这只是对描述器的原始调用:

    samplePtr->~sample(); // CORRECT
    
    您所做的(使用
    free
    释放
    malloc
    未分配的内存)会导致未定义的行为-任何情况都可能发生。与通过
    new
    获取的指针的
    delete
    相同。与
    delete
    ing从
    malloc
    获取的指针相同或相反


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

    这就是为什么placement new可能不好(事实上,您应该尽可能避免它,在这种情况下,只需堆栈分配对象),您不应该
    删除
    内存(因为它从来不是由
    new
    首先创建的,相反,您需要执行
    samplePtr->~sample();

    谢谢,我现在就知道了。我只需要调用析构函数。一旦对象自动超出范围,堆栈上相应的内存将被释放。
    samplePtr->~sample(); // CORRECT