如果在C ++中的私有函数中分配内存,是否可以在析构函数中释放内存?

时间:2011-07-25 18:28:43

标签: c++ memory constructor destructor

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

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,因此在尝试删除未分配的指针时会产生混淆。 (2)在我的范围内实际上有两个类的实例,这是我的错误。在最终的代码中,只会有一个实例。谢谢大家!

3 个答案:

答案 0 :(得分:5)

将指针初始化为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;
         }
    }
}

答案 1 :(得分:3)

您必须在构造函数中将实例变量TransferTracker的值初始化为0。您遇到的问题是Simulation类的销毁,而实际上没有为TransferTracker分配动态内存。

使用空指针在析构函数中调用delete[]是安全的。问题是,如果您没有为TransferTracker提供值,则可能会有任何未定义的值,这会导致尝试使用delete[]解除分配时出现问题。

编辑

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

答案 2 :(得分:1)

我怀疑原因是当你没有调用calc()函数时你的析构函数被调用,因此尚未分配内存。

您希望设置一个“警卫”,以确保您在尝试释放TransferTracker的内存之前已经分配了内存。