用C ++清理动态的对象数组

时间:2010-03-20 09:41:20

标签: c++ object reference dynamic-arrays delete-operator

我对在C ++中处理一个对象数组感到困惑,因为我似乎无法找到有关它们如何传递的信息(引用或值)以及它们如何存储在数组中。

我希望对象数组是指向该对象类型的指针数组,但我没有在任何地方找到它。它们是指针,还是对象本身会在数组的内存中布局?

在下面的示例中,自定义类myClass包含一个字符串(这会使它具有可变大小,或者字符串对象是否包含指向字符串的指针,因此占用一定量的空间。我尝试创建一个myContainer中的myClass对象的动态数组。在myContainer.addObject()方法中,我尝试创建一个更大的数组,将所有对象与一个新对象一起复制到其中,然后删除旧对象。我一点也不自信我正在用我的析构师正确地清理我的记忆 - 我可以在这方面做些什么改进?

class myClass
{
    private:
          string myName;
          unsigned short myAmount;

    public:
        myClass(string name, unsigned short amount)
        {
            myName = name;
        myAmount = amount;
        }

    //Do I need a destructor here? I don't think so because I don't do any
    // dynamic memory allocation within this class
};



class myContainer
{
    int numObjects;
    myClass * myObjects;

   public:
    myContainer()
    {
        numObjects = 0;
    }   

    ~myContainer()
    {
        //Is this sufficient?
        //Or do I need to iterate through myObjects and delete each
        // individually?
        delete [] myObjects;
    }


    void addObject(string name, unsigned short amount)
    {
        myClass newObject = new myClass(name, amount);

        myClass * tempObjects;
        tempObjects = new myClass[numObjects+1];
        for (int i=0; i<numObjects; i++)
            tempObjects[i] = myObjects[i]);
        tempObjects[numObjects] = newObject;
        numObjects++;
        delete newObject;

        //Will this delete all my objects? I think it won't.
        //I'm just trying to delete the old array, and have the new array hold
        // all the objects plus the new object.
        delete [] myObjects;
        myObjects = tempObjects;
    }
};

4 个答案:

答案 0 :(得分:3)

不,动态数组不是指向该类型的指针数组 - 它是指向第一个元素的指针。元素在内存中连续布局,并在数组delete[]时被销毁。

因此,您的释放看起来很好 - 您创建了myClass个对象的动态数组,因此您不必单独delete它们。如果你有一个指向(动态分配的)对象的指针数组,你只需要这样做。

但有两个明确的错误:

tempObjects[numObjects] = newObject; // assign a myClass pointer to a myClass instance?

这应该是例如:

tempObjects[numObjects] = myClass(name, amount);

此外,myObjects永远不会被初始化,这意味着它包含垃圾,解除引用/使用它会导致未定义的行为。

最后,除非您出于学习目的而这样做,否则只需使用像std::vector这样的容器来为您完成所有工作。

答案 1 :(得分:3)

C ++中的数组是在内存中布置的对象数组。 例如在:

struct pair {
   int x; int y;
};
...
pair array[10];

数组中的每个项目的大小都是两个整数。 如果你想要一个指针数组,你可以简单地声明一个:

pair* array_of_pointers[10];

字符串对象具有指向字符串的可变大小部分的指针。所以他们很安全。 事实上,他们是这里的重要教训。使用字符串类来避免过多的内存处理,可以使用vector类来避免处理动态数组的所有麻烦。

对于你正在做这个练习的情况。以下是一些问题: newObject需要在本地分配,而不需要new。这将使代码正确(因为newObject不是指针而new返回指针)并且还将为您省去显式处理内存的麻烦。 (在更高级的说明中,这使得代码异常在另一个位置安全) 永远不会初始化myObject。并且您不在构造函数中使用初始化列表。构造函数应如下所示:

myContainer() : numObjects(0), myObjects(NULL)
{

}  

代码中的析构函数完全符合它们的要求。

答案 2 :(得分:1)

我希望对象数组是指向该对象类型的指针数组,但我没有在任何地方找到它。它们是指针,还是对象本身会在数组的内存中布局?

数组将由对象本身组成。如果你想拥有一个指针数组,你必须声明:

myClass ** tempObjects;  
tempObjects = new myClass*[numObjects+1];  

我假设你已经习惯了C#或Java?在这些语言中,对象只能在堆上分配,并且始终通过引用来访问。它可以在C ++中实现,但在C ++中,您也可以将对象直接放在堆栈上,或直接构造对象本身的数组。

在下面的示例中,自定义类myClass包含一个字符串(这会使它变为可变大小,或者字符串对象是否包含指向字符串的指针,因此占用一定量的空间?

第二个:字符串对象本身的大小是常量,但是有一个指向从堆分配的动态大小缓冲区的指针。

我认为解除分配看起来很好。代码可以通过各种方式更有效地编写,但看起来是正确的。

答案 3 :(得分:0)

尝试测试它,看看会发生什么(是的,这可能是编译器特定的,但仍然)... 您可以尝试向myClass添加自定义析构函数(即使您不需要),在调用时递增“全局”计数器,然后在删除数组后打印计数器。

我希望调用每个对象的析构函数。请注意,对象通常存储在“按指针”中,以允许将继承的对象放入数组中(避免“切片”)。