C++如何给ZooObject类对象二维数组分配内存并完成初始化?
问题解答
合法性判定
你给出的ZooObject ***zooArray声明是完全合法的。该变量本质是存储ZooObject*类型指针的二维数组,由于Animal是ZooObject的公有派生类,C++支持基类指针指向派生类实例的多态规则,因此完全可以用这个二维数组存储Animal对象的地址。
原有代码的核心错误
原有代码的实现存在三个致命问题,运行会直接崩溃或出现未定义行为:
- 缺少
zooArray本身的内存分配:ZooObject***是三级指针,首先需要分配rows个ZooObject**类型的空间存储行指针,原有代码直接访问zooArray[i]属于野指针访问。 - 栈局部对象悬空指针:内层循环中创建的
Animal animal是栈上的局部变量,每次循环结束就会被销毁,赋值给zooArray[i][j]的地址是非法的悬空指针,后续访问会出现不可预期的错误。 - 循环变量
i、j未声明,代码无法通过编译。
正确的初始化实现
首先需要给ZooObject补充虚析构函数,避免后续释放内存时出现派生类资源泄漏,其次按以下步骤实现构造和析构逻辑:
修正后完整代码
class ZooObject { public: bool isAlive; // 基类添加虚析构函数,保证多态场景下派生类能正确析构 virtual ~ZooObject() = default; }; class Animal : public ZooObject { public: bool isHerbivore; }; class Zoo { public: int rows, cols; ZooObject ***zooArray; Zoo(int rows, int cols) : rows(rows), cols(cols) { // 第一步:分配行指针数组,共rows个ZooObject**元素 zooArray = new ZooObject**[rows]; // 第二步:给每一行分配列指针数组,共cols个ZooObject*元素 for (int i = 0; i < rows; i++) { zooArray[i] = new ZooObject *[cols]; // 第三步:每个位置初始化堆上的Animal实例 for (int j = 0; j < cols; j++) { zooArray[i][j] = new Animal(); // 如果需要初始化为空,赋值为nullptr即可,后续使用时再赋值 } } } // 补充析构函数释放内存,避免泄漏 ~Zoo() { for (int i = 0; i < rows; i++) { // 先释放每个元素 for (int j = 0; j < cols; j++) { delete zooArray[i][j]; } // 释放当前行的指针数组 delete[] zooArray[i]; } // 释放行指针数组本身 delete[] zooArray; } }; int main() { Zoo *zoo = new Zoo(3, 3); // 自定义使用zoo的业务逻辑 delete zoo; return 0; }
注意事项
- 如果不需要在初始化时就创建
Animal实例,可以把第三步的new Animal()替换为nullptr,后续使用时再给对应位置赋值堆上的对象地址即可。 - 如果没有特殊需求,更推荐使用STL容器
std::vector<std::vector<ZooObject*>>代替手动管理的三级指针,可以避免大量内存管理的错误。
内容的提问来源于stack exchange,提问作者taurus05
相关产品推荐
相关产品推荐

