删除向量中的元素(对象)(未被指针引用),内存处理

时间:2010-02-10 11:37:05

标签: c++

这是this question的扩展。我在网上搜索过但找不到满意的答案。

我有一个class A,它定义了一个包含许多class Region个实例的向量。这些Region实例的内存处理需要由Class A

进行管理

我的问题是:

1。在以下代码段中,是否需要在A类的desctuctor中显式删除这些实例?

2。我应该将实例创建为new Region(i)吗?它是否比第一个选项更好(不使用new)A类是一个相当大的对象。我该如何确定是否使用新的?

3. 如果对#2的回答是肯定的,我应该如何在析构函数中删除这些实例? delete Region(i)(在for循环中)或delete [] reg ??我猜测以前的方式是正确的方法,但想确认一下。

4. 除了“区域实例未被删除”之外,您是否看到任何明显的内存泄漏...尤其是在A的构造函数中构造Region对象时? / p>

class Region{
   public:
      Region(int num);
      int number;
      std::vector <elemt*> elements;   
      int info;
}

class A{
public:
    std::vector<Region> reg;
    const int numOfRegions = 100;
}

A::A(){
    int i;
    for ( i=0; i<numOfRegions; i++){
        reg.push_back(Region(i));
      } 
}

A::~A(){
  // How should the elements within vector Region be deleted??
  // Should I use "new" to allocate memory to instances of Region()
}

更新 非常感谢所有回答的人!

4 个答案:

答案 0 :(得分:3)

  1. 没有。 std::vectorRegion存储为对象,并在添加/删除/覆盖元素时调用必要的(de)构造函数。

  2. 没有。仅当您将矢量声明为std::vector<Region *> reg;时。如果Region是多态的,或者复制/赋值构造函数很昂贵(矢量经常复制元素),则必须这样做。

  3. 如果您将它们存储为指针,则需要迭代reg并使用delete ptr;删除每个元素。

  4. 根据您创建elemt类实例的方式,您可能需要向Region添加析构函数以销毁这些实例。

答案 1 :(得分:3)

  

在以下代码段中,我是否需要明确删除这些代码段   在课堂上的实例   ?A

不 - 它们会自动删除 - 如果您不使用new创建它,则不要删除它。

  

我应该将实例创建为新的Region(i)吗?是不是更好   第一个选项(不使用新的)A类   是一个很大的对象。我该怎么办?   确定是否使用新的?

A的大小不是问题。这个问题没有明确的答案,但一般规则是,如果你不必使用new动态创建对象,那么就不要这样做。

  

如果对#2的回答是肯定的,我应该如何删除这些实例   析构函数?删除区域(i)(在   for loop)或删除[] reg ??我是   猜测以前的方式是正确的   方式,但想确认。

如果您使用new创建它们,则可以在for循环中删除它们:

 delete reg[i];
当然,reg必须是一个指针向量。更好的选择是使用智能指针向量。

  

除了“区域实例未被删除”之外,您是否看到任何明显的情况   内存泄漏..特别是在   A中Region对象的构造   构造

它们被删除 - 只是不是你。这被称为RAII,是非常非常好的C ++实践 - 你应该尽可能使用RAII。

答案 2 :(得分:1)

class A内,一切似乎都被定义好了。 (你需要整理课堂宣言)。这意味着当A的实例被销毁时,一切都将被自动销毁。是的,我的意思是std::vector reg;会破坏自己,以及它负责的Region个实例的所有副本。

你真的在问class Region及其vector哪个有指针,虽然你没有显示任何代码可能需要删除它的指针?

修改

首先修改Region的详细信息,第二次修改会删除它们并添加A::addRegions

我认为这就是你所追求的目标:

#include <vector>

class Region{
   public:
      Region(int num);
      // Details of Region removed
};

class A{
    std::vector<Region> reg;
    const int numOfRegions;
public:
    A();
    // No destructor needed: ~A();
    void addRegions(int num);
};

A::A():numOfRegions(100){
    for (int i=0; i<numOfRegions; ++i){
        reg.push_back(Region(i));
      } 
}
void A::addRegions(int num)
{
    for (int i=0; i<num; ++i){
         reg.push_back(Region(i));
    } 
}

注意class A没有析构函数。

A::addRegions也使用push_back,即使现在也不需要析构函数。

还要注意类声明如何在它们之后有分号,并且A的构造函数初始化numOfRegions

答案 3 :(得分:1)

1。在您的示例中,您唯一需要明确删除的是elemt*,如果它们是动态分配的。如果是这样,必须通过拥有它们来删除它们。如果您的Region仅指向它们,则不应在其析构函数中删除它们。

2。首先,您的向量在堆栈中分配,并且将被解除分配而不会出现问题。其次,要使用new Region(i),您需要更改class A声明。但在你的情况下,没有必要这样做。您应该使用operator new的几个示例:
1)需要更持久的数据,因为动态分配的数据将持续存在,直到明确解除分配(并且只要保持指针指向它就可以访问)
2)您的对象可能太大而无法全部存储在堆栈中。

3。如果您确实使用了new Region(i),那么您可能会在某些时候使用operator delete(可能是在析构函数或其他清理函数上)来正确释放它。

4。只有在elemt向量中直接创建新的elements时,您的构造函数才会出现问题,例如elements.push_back(new elemt())。这是一种危险的设计,可能会导致多次内存泄漏或出现seg故障的风险。如果你想以这种方式分配它们,你需要一个支持复制机制的智能指针,如shared pointer