我不允许使用Vectors专门用于此学校作业。我找到的大多数答案都只是简单地说"你应该使用向量",这是投票最多的评论。虽然我很感激并理解这一点,但我只是被限制在这项任务中使用它们。
这是一个具有动态内存管理的C++分配,如下所示:
// property in header declaration
int numAnimals;
int capacity;
Animal** animals;
void addAnimal(Animal *newAnimal);
// class implementation
capacity = 10;
numAnimals = 0;
animals = new Animal*[capacity];
void SampleClass::addAnimal(Animal *newAnimal)
{
for (int i = 0; i < capacity; i++){
if(animals[i]){
// animal object already exists in array, move on
i++;
}else{
animals[i] = newAnimal;
numAnimals++;
break;
}
}
}
animals是指向指针的指针,在本例中是指向尚未创建的对象类型Animal的指针数组的指针。
使用"addAnimal"函数,我试图通过循环指针数组将动物对象添加到数组中,如果已经存在动物对象,则迭代到下一个索引。如果没有动物,则将该动物插入阵列中。
当我试图访问数组中动物对象的成员函数时,抛出了一个异常"读取访问违规">。
我的怀疑是因为:如果(animals[i])可能没有做我认为它在做的事情,通过调试器运行它,我从来没有碰到"else"部分,所以当方法完成时,数组中仍然充满了没有设置到任何对象的指针。因此,当我试图访问一个成员函数时,它是一个不存在的对象。
那么,如果我的怀疑是正确的,那么以这种方式将新对象插入指针数组的最佳方法是什么?它们必须是指针,否则它会自动创建一个充满填充对象的数组,这不是我想要的。
我没有发布所有的代码,因为我想让我的问题简短,很抱歉,我是C++和stackoverflow的新手。是的,我知道删除[]以清除记忆。
感谢您的帮助!
由于在numAnimals
中,您会记录数组中动物指针的当前数量,因此不需要for
循环来找到第一个可用的插槽来添加新的动物指针(还要注意,假设您想使用代码中所示的for
循环,则必须注意将数组中的所有初始指针正确初始化为nullptr
)。
你可以使用:
// Inside SampleClass::addAnimal(Animal *newAnimal):
animals[numAnimals] = newAnimal;
numAnimals++;
请注意,当你插入新动物时,你必须注意而不是溢出你的数组容量
因此,在插入新动物之前,您必须检查阵列中是否有足够的空间,例如:
// Before inserting:
if (numAnimals == capacity)
{
// You ran out of capacity.
//
// 1. Allocate a new array with bigger capacity (e.g. 2X)
// 2. Copy the content from the current array to the new one
// 3. delete current array
}
附带说明:
是的,我知道
delete[]
在之后清除内存
请注意,如果在指针的animals
数组上调用delete[]
,则会释放此指针数组,但不会指向的Animal
对象。
int capacity = 10;
Animal** animals = new Animal*[capacity];
这分配了十个指针,除了它不进行初始化,这意味着您基本上拥有垃圾数据。
if (animals[i])
这是针对nullptr
测试其中一个指针,但由于您这样做了没有初始化,它不太可能是nullptr
。
您需要添加一个循环传递,在您之后立即清空数据分配:
for(int i=0; i<capacity; ++i)
animals[i] = nullptr;
还有一个错误:
if (animals[i]) {
// animal object already exists in array, move on
i++; // <- here
这是错误的,您在上移动两次for (int i = 0; i < capacity;
i++)
不管老师怎么说,"使用向量"是正确的方法。然而,如果你应该手动管理动态数组,那么你能做的最好的事情就是将所有脏内存封装在class
中,并编写自己的std::vector
替代品。也就是说,为了避免动态分配遍布代码(尤其是在那些应该处理Animal
的地方,而不应该关心手动分配内存等),你应该编写一个class
,它可以做到这一点(而不是其他),并提供更好的接口。我只能在这里概述一下这个想法:
template <typename T>
class my_vector {
private:
T* data;
size_t size;
size_t capacity;
public:
void push_back(const T& t);
size_t size();
T& operator[](size_t index);
void resize(size_t size);
//... etc...
};