如果在c++的私有函数中分配了内存,可以在析构函数中释放内存吗?

Can one deallocate memory in a destructor if they allocated memory within a private function in C++?

本文关键字:内存 释放 析构函数 分配 c++ 如果 函数      更新时间:2023-10-16

我试图在全局范围内定义一个包含一些动态分配数组的类。当调用类的构造函数时,程序无法访问通过参数文件读取的用户定义参数(即模拟中的年数),因此它无法将内存分配到适当的大小。我的想法是在类中的私有函数中分配内存,然后使用析构函数释放内存。一些示例代码:

class Simulation{
private:
    int initial_call; //a flag used to initialize memory
    double *TransferTracker;
public:
    Simulation();
    ~Simulation();
    void calc();
};
Simulation simulator; //global instance of Simulation
Simulation::Simulation()
{
   initial_call = 1;
}
Simulation::~Simulation()
{
    //when calling the destructor, though, the address is
    //0xcccccccc and the following attempt to delete produces
    //the compiler error.
    delete [] TransferTracker; //see error
}
void Simulation::calc()
{
    for (int i = 0; i < num_its; i++)
    {
         if (initial_call)
         {
             TransferTracker = new double [5];
             //The address assigned is, for example, 0x004ce3e0
             initial_call = 0;
         }
    }
    //even if this calc function is called multiple times, I see
    //that the address is still 0x004ce3e0.
}
我从上面的代码片段收到的错误是:
 Unhandled exception at 0x5d4e57aa (msvcr100d.dll) in LRGV_SAMPLER.exe: 0xC0000005: Access    
 violation reading location 0xccccccc0.

这个错误是有意义的,因为我在进入析构函数时检查了TransferTracker的内存地址。我的问题是,为什么我们在进入析构函数时会丢失地址?这可能与模拟器是全局的有关;如果类不是全局的,这种范式似乎工作得很好。我是面向对象编程的新手,所以任何帮助都很感激!

编辑:这基本上是我的一个错误,并得到了答案的帮助。出现了两个问题:(1)指针从未设置为NULL,从而在试图删除未分配的指针时造成混乱。在我的作用域中实际上有两个类的实例,这是我的一个错误。在最后的代码中,只会有一个实例。谢谢大家!

将指针初始化为NULL (0)

Simulation::Simulation() : TransferTracker(NULL)
{
  initial_call = 1;
}
Simulation::~Simulation()
{
  //when calling the destructor, though, the address is
  //0xcccccccc and the following attempt to delete produces
  //the compiler error.
  if(TransferTracker) delete [] TransferTracker; //see error
  TransferTracker = NULL;
}

这样当你想要删除它时,你可以检查它是否被初始化。这是最佳实践,所以总是这样做,不仅仅是在构造

编辑:

void Simulation::calc()
{
    for (int i = 0; i < num_its; i++)
    {
         if (initial_call)
         {
             if(TransferTracker) delete []  TransferTracker;
             TransferTracker = new double [5];
             initial_call = 0;
         }
    }
}

必须在构造函数中将实例变量TransferTracker的值初始化为0。您所遇到的问题是在没有实际为TransferTracker分配动态内存的情况下破坏了Simulation类。

在析构函数中使用空指针调用delete[]是安全的。问题是,如果你不给TransferTracker赋值,它可能有任何未定义的值,这将导致在试图释放delete[]时遇到麻烦。

编辑:

根据你的编辑,你如何确保只有一个Simulation类的实例?这与您是否在构建中包含几个.o文件等有关。

我怀疑原因是在您还没有调用calc()函数时调用了析构函数,因此还没有分配内存。

你想要设置一个"保护",以确保在试图为TransferTracker释放内存之前已经分配了内存。