You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

类中动态内存分配问题求助:披萨店程序运行异常排查

排查你的披萨店程序冻结问题

看起来你遇到的核心问题是缺少拷贝构造函数导致的浅拷贝内存错误,再加上一些逻辑和初始化问题,最终导致程序卡住或者崩溃。咱们一步步来拆解:

1. 最致命的问题:Pizza类缺失拷贝构造函数

你在Pizza类里使用了动态分配的char* ingredients,但没有自定义拷贝构造函数。当你做这些操作时:

  • 把Pizza对象以值传递的方式传给areSame(Pizza p)
  • 在Pizzeria扩容动态数组时,复制旧数组里的Pizza元素到新数组

C++会自动调用默认拷贝构造函数,它做的是浅拷贝——也就是直接复制指针值,而不是复制指针指向的内存。这会导致多个Pizza对象的ingredients指向同一块内存:

  • 当其中一个对象析构时,会delete[] ingredients释放这块内存
  • 剩下的对象的ingredients就变成了野指针,后续对它的任何操作(比如访问、再次释放)都会导致内存混乱,轻则程序卡住,重则直接崩溃。

修复方法:添加自定义拷贝构造函数

在Pizza类的public部分添加:

Pizza(const Pizza& other) {
    // 复制name数组
    strcpy(this->name, other.name);
    this->price = other.price;
    this->reduction = other.reduction;
    // 深拷贝ingredients
    this->ingredients = new char[strlen(other.ingredients) + 1];
    strcpy(this->ingredients, other.ingredients);
}

同时,为了遵循三法则(如果定义了拷贝构造、析构、拷贝赋值中的一个,通常需要定义另外两个),还要添加拷贝赋值运算符:

Pizza& operator=(const Pizza& other) {
    if (this == &other) { // 防止自赋值
        return *this;
    }
    // 先释放当前对象的ingredients内存
    delete[] this->ingredients;
    // 复制其他成员
    strcpy(this->name, other.name);
    this->price = other.price;
    this->reduction = other.reduction;
    // 深拷贝新的ingredients
    this->ingredients = new char[strlen(other.ingredients) + 1];
    strcpy(this->ingredients, other.ingredients);
    return *this;
}

2. areSame函数的逻辑错误

你写的areSame函数逻辑完全反了,而且效率低下:

bool areSame(Pizza p) {
    for (int i = 0; i < strlen(this->ingredients) + 1; i++)
        if (this->ingredients[i] != p.ingredients[i])
            return true; // 这里错了!不一样应该返回false
    return false; // 一样反而返回false?
}

改成用标准库的strcmp更简洁可靠,同时用引用传递避免不必要的拷贝:

bool areSame(const Pizza& p) {
    // 比较name和ingredients,都相同才返回true
    return strcmp(this->name, p.name) == 0 && strcmp(this->ingredients, p.ingredients) == 0;
}

3. Pizzeria类的初始化问题

你贴的Pizzeria构造函数代码不完整,假设你没初始化p和number_of_pizzas,那p会是一个野指针,后续扩容时操作野指针肯定会出问题。正确的构造函数应该是:

Pizzeria(char *name= "") {
    strcpy(this->name, name);
    this->p = nullptr; // 初始化动态数组指针为空
    this->number_of_pizzas = 0; // 初始化披萨数量为0
}

另外,Pizzeria类也需要析构函数来释放动态数组的内存,避免内存泄漏:

~Pizzeria() {
    delete[] p; // 释放存储披萨的动态数组
}

4. 关于addPizza函数的注意事项

假设你的addPizza函数逻辑是扩容数组,那正确的实现应该是这样(参考):

void addPizza(const Pizza& newPizza) {
    // 创建新的更大的数组(容量+1)
    Pizza* newArr = new Pizza[number_of_pizzas + 1];
    // 复制旧数组的元素到新数组
    for (int i = 0; i < number_of_pizzas; i++) {
        newArr[i] = p[i]; // 这里会调用我们刚才写的拷贝赋值运算符,深拷贝
    }
    // 添加新披萨
    newArr[number_of_pizzas] = newPizza;
    // 释放旧数组的内存
    delete[] p;
    // 更新指针和数量
    p = newArr;
    number_of_pizzas++;
}

这里用const Pizza&传递新披萨,避免不必要的拷贝,同时保证安全。

总结

程序卡住的核心原因是浅拷贝导致的内存野指针问题,补上拷贝构造和拷贝赋值运算符就能解决大部分问题。另外修正areSame的逻辑错误,确保类成员正确初始化,你的程序应该就能正常运行了。

内容的提问来源于stack exchange,提问作者NikolaS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:58:58