【问题标题】:Proper destruction of pointers to objects正确销毁指向对象的指针
【发布时间】:2012-11-30 11:08:39
【问题描述】:

我想问几个关于正确销毁 int 指针和向量指针的问题。首先,我看到过去有人问过这类问题,几乎总是有几个回答说在 C++ 中使用向量指针、对象指针等不是很好的标准 C++ 编码实践,你应该实例化一个对象的副本。这可能是真的,但你并不总是能够控制在你到达之前已经奠定的范式。我需要使用的范例需要初始化指向几乎所有内容的指针。一种非常类似于 Java 的 C++ 方法。我们这样做的主要原因之一是我们的数据集太大,堆栈分配可能会溢出。

我的问题:

如果我有一个指向 int32_t 数组的指针,那么在析构函数中销毁它的正确方法是什么?

注意:我们的做法是在构造函数中将任何指针设置为 NULL。

I initialize it as a member variable. 
int32_t *myArray_;

When I use it in a method, I would:
this->myArray = new int32_t[50];

To delete it in the method I would call delete on the array:
delete [] this->myArray;

What is the proper call in the destructor?
~MyDestructor(){

    delete this->myArray_;
    or delete [] this->myArray_;

}

关于向量指针我也有同样的问题:

I initialize it as a member variable. 
std::vector<MyObject*> *myVector_;

When I use it in a method, I would:
this->myVector_ = new std::vector<MyObject*>();


//pushback some objects

To delete the vector in the method I would iterate the vector and delete its objects, then    delete the vector;

 for(std::vector<MyObject*>::iterator itr = this->myVector_->begin(); 
 its != this->myVector->end(); ++ itr){

      delete (*itr);

}

delete this->myVector_;


What would be the proper way to clean it up in the destructor?
would I just delete the vector?

delete this->myVector;

or do I need to iterate the entire vector again?

提前感谢您的任何建议。

【问题讨论】:

  • new[] --> delete[]new --> delete.
  • 为什么会有vector&lt;&gt;*std::vector&lt;&gt; 不会在堆栈上进行大量分配(在内部它从堆中分配对象),因此通常没有充分的理由动态分配 std::vectors&lt;&gt;
  • @Chad 使用向量指针是有正当理由的;一种情况是,如果 API 已经有工厂向您提供向量,但您有责任销毁它。
  • 代码确实没有有一个“指向[n] int32_t数组的指针”。它有一个指向int32_t 的指针。
  • 将内存管理强加给用户的 API 是邪恶的。

标签: c++ pointers memory-management


【解决方案1】:

new 分配的任何东西都应该用delete 释放。

int* p = new int;
delete p;

new [] 分配的任何东西都应该用delete [] 释放。

int* p = new int[10];
delete [] p;

任何动态分配和存储在vector 中的东西都需要手动释放:

std::vector<int*> v;
v.push_back(new int(1));
v.push_back(new int(2));

for(std::vector<int*>::iterator i = v.begin(), e = v.end(); i != e; ++i)
   delete (*i);

如果出于某种奇怪的原因,您认为动态分配 vector 是合适的,则适用相同的规则。

std::vector<int*>* v = new std::vector<int*>;
v->push_back(new int(1));
v->push_back(new int(2));

for(std::vector<int*>::iterator i = v->begin(), e = v->end(); i != v; ++i)
   delete (*i);

delete v;

但是,我建议动态分配 std::vector 的原因很少。

在 C++11 中,最好的方法是使用 std::unique_ptr:

std::unique_ptr<int> p(new int);
// std::unique_ptr handles clean up for you


std::unique_ptr<int[]> p(new int[10]);
// std::unique_ptr handles clean up for you for arrays too!

如果你有一个类的成员变量,同样的规则适用:

class Foo
{
   Foo()
      : bar_(new int)
      , bar2_(new int[20])
   {
   }

   ~Foo()
   {
      delete [] bar2_;
      delete bar_;
   }

   int* bar_;
   int* bar2_;
};

但即便如此,将它们设为std::unique_ptr 更有意义,您甚至可以在需要时将它们视为接口中的原始指针:

class Foo
{
   Foo()
     : bar_(new int)
     , bar2_(new int[20])
   {
   }

   int* get_bar()
   {
      return bar_.get();
   }

   int* get_bar2()
   {
      return bar2_.get();
   }

   std::unique_ptr<int> bar_;
   std::unique_ptr<int[]> bar2_;
};

【讨论】:

  • 关于删除/删除[] 的规则并不总是正确的。考虑typedef int mytype[42]; int* x = new mytype;。现在你需要delete[] x;,即使你使用的是new而不是new[]
  • 谢谢乍得。我真的很感激。因此,在 int32_t* 的示例中;在我的方法中,我将它初始化为 myArray = new int32_t[50]。在方法中,我会使用 delete[] myArray_ 删除它,但在析构函数中,我会使用 delete myArray_ 因为它不再定义为 new int32_[50] ?
  • 不,如果你用new[]初始化它,使用delete[],即使它在另一个(后来的)方法中。我已经用更多细节更新了我的答案。
  • @Chad:因为您仍然有错误的规则“任何用 new 分配的东西都应该用 delete 解除分配”。
  • @etarion 你能解释为什么这是个问题吗?智能指针(例如std::unique_ptr)是否抽象了该规则,您可能会在用户代码中看到new,而在用户代码中没有相应的delete
猜你喜欢
  • 2013-11-27
  • 1970-01-01
  • 2019-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-28
  • 1970-01-01
  • 2013-07-25
相关资源
最近更新 更多