1

我对在 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

4 回答 4

3

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

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

但是有两个明确的错误:

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

这应该是例如:

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

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

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

于 2010-03-20T09:55:23.950 回答
3

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

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

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

pair* array_of_pointers[10];

字符串对象具有指向字符串可变大小部分的指针。所以他们是安全的。事实上,它们是这里重要的一课。与使用字符串类来避免过多的内存处理相同的方式,您可以使用向量类来避免处理动态数组的所有麻烦。

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

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

}  

代码中的析构函数与它们应有的完全一样。

于 2010-03-20T10:12:58.423 回答
1

我希望一个对象数组是一个指向该对象类型的指针数组,但我还没有发现这个写在任何地方。它们会是指针,还是对象本身会以数组的形式排列在内存中?

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

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

我假设您习惯于 C# 或 Java?在那些语言中,对象只能在堆上分配,并且总是通过引用来访问。这在 C++ 中是可能的,但在 C++ 中,您也可以将对象直接放在堆栈上,或者直接构造对象本身的数组。

在下面的示例中,自定义类 myClass 包含一个字符串(这会使其具有可变大小,还是字符串对象包含指向字符串的指针并因此占用一致的空间量?

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

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

于 2010-03-20T10:01:22.627 回答
0

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

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

于 2010-03-20T09:55:32.187 回答