我的park_car函数有什么问题?

时间:2012-05-20 23:46:52

标签: c++ multidimensional-array heap

我正在为学校做一个任务,我正在慢慢地实现它,我不知道为什么我的park_car功能不起作用,我只是想做一个测试,程序崩溃了..这是我的代码。

PS:我无法更改***p2parkboxes,因为它与大多数其他变量一样在初始文件中给出。我只想看看0楼的第一个元素:HH-AB 1234.非常感谢你的帮助。 PS2:我不能使用std :: string,也不允许执行该任务。

#include <iostream>
#include <cstring>
using namespace std;

#define EMPTY "----------"
class Parkbox{
    char *license_plate; // car's license plate
    public:
    Parkbox(char *s = EMPTY); // CTOR
    ~Parkbox(); // DTOR
    char *get_plate(){return license_plate;}
};
class ParkingGarage{
    Parkbox ***p2parkboxes;
    //int dimensions_of_parkhouse[3]; // better with rows,columns,floors
    int rows,columns,floors; // dimensions of park house
    int total_num_of_cars_currently_parked;
    int next_free_parking_position[3];
    // PRIVATE MEMBER FUNCTION
    void find_next_free_parking_position();
    public:
    ParkingGarage(int row, int col, int flr);// CTOR,[rows][columns][floors]
    ~ParkingGarage(); // DTOR
    bool park_car(char*); // park car with license plate
    bool fetch_car(char*); // fetch car with license plate
    void show(); // show content of garage floor
    // by floor
};

Parkbox::Parkbox(char *s ) { // CTOR
    license_plate = new char[strlen(s)+1];
    strcpy(license_plate, s);
    //cout << "ParkBox CTOR" << endl;
}
Parkbox::~Parkbox() { // DTOR
    delete [] license_plate;
    //cout << "ParkBox DTOR" << endl;
}

ParkingGarage::ParkingGarage(int row, int col, int flr){
    rows = row; columns = col; floors = flr;
    p2parkboxes = new Parkbox**[row];
    for (int i = 0; i < row; ++i) {
        p2parkboxes[i] = new Parkbox*[col];

        for (int j = 0; j < col; ++j)
            p2parkboxes[i][j] = new Parkbox[flr];
    }

}

ParkingGarage::~ParkingGarage(){

    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < columns; ++j)
            delete [] p2parkboxes[i][j];

        delete [] p2parkboxes[i];
    }
    delete [] p2parkboxes;
}

void ParkingGarage::show(){
    int i,j,k;
    for (i = 0 ; i < floors; i++){
        cout << "Floor" << i << endl;
        for (j=0;j<rows;j++){
            for (k=0;k<columns;k++){
                cout << p2parkboxes[j][k][i].get_plate() << "  ";
            }
            cout << endl;
        }
    }
}

bool ParkingGarage::park_car(char*s){

    p2parkboxes[0][0][0] = Parkbox(s); //test
    //p2parkboxes[0][0][0] = s; //test

    return true;
}


int main(void) {
    // a parking garage with 2 rows, 3 columns and 4 floors
    ParkingGarage pg1(2, 3, 4);
    pg1.park_car("HH-AB 1234");
    /*pg1.park_car("HH-CD 5678");
      pg1.park_car("HH-EF 1010");
      pg1.park_car("HH-GH 1235");
      pg1.park_car("HH-IJ 5676");
      pg1.park_car("HH-LM 1017");
      pg1.park_car("HH-MN 1111"); */
    pg1.show();
    /*pg1.fetch_car("HH-CD 5678");
      pg1.show();
      pg1.fetch_car("HH-IJ 5676");
      pg1.show();
      pg1.park_car("HH-SK 1087");
      pg1.show();
      pg1.park_car("SE-AB 1000");
      pg1.show();
      pg1.park_car("PI-XY 9999");
      pg1.show(); */
    return 0;
}

3 个答案:

答案 0 :(得分:6)

您没有声明Parkbox类的复制构造函数。那么,行

p2parboxes[0][0][0] = Parkbox(s)

在堆栈上创建一些东西(带有char *指针的Parkbox实例)(并且几乎立即删除它)。要更正此问题,您可以定义

Parkbox& operator = Parkbox(const Parkbox& other)
{
    license_plate = new char[strlen(other.get_plate())+1];
    strcpy(license_plate, other.get_plate());
    return *this;
}

让我们看看

的工作流程
p2parboxes[0][0][0] = Parkbox(s)

线。

  1. 首先,调用构造函数并在堆栈上创建Parkbox实例(我们将调用此tmp_Parkbox)。
  2. 在这个构造函数中,license_plate被分配,让我们说它指向0xDEADBEEF位置。
  3. 复制发生(这很明显,因为这个是用代码编写的东西)而p2parboxes [0] [0] [0]现在包含tmp_Parkbox的确切副本。
  4. tmp_Parkbox的范围现在结束,并且调用了tmp_Parkbox的析构函数,其中tmp_Parkbox.license_plate(0xDEADBEEF ptr)被释放。
  5. p2parboxes [0] [0] [0]仍然包含Parkbox的“有效”实例,而p2parboxes [0] [0] [0] .license_plate仍然是0xDEADBEEF,导致未定义的行为,如果在调用

    之前进行任何分配

    cout&lt;&lt; p2parboxes [0] [0] [0] .license_plate;

  6. 结论:行本身没有任何问题,问题隐藏在'='运算符的实现细节中。

    在这一点上,你最好使用std :: string作为字符串,而不是使用尖锐,棘手和显式的C风格直接内存管理与隐式C ++复制/构造语义混合。如果将std :: vector用于动态数组,代码也会更好。

答案 1 :(得分:2)

这里的问题是您没有深层复制分配语义。当您将临时Parkbox分配给停车库中的Parkbox时,编译器生成的赋值运算符会生成指针license_plate的浅表副本,从而使两个Parkbox指向相同的内存位置。然后临时Parkbox超出范围并删除license_plate。由于其他Parkbox指向同一位置,因此license_plate也会被删除。

有几种解决方案。解决该问题的一种方法是定义赋值运算符和复制构造函数,其提供适当的语义,即执行牌照字符串的深拷贝。更好的选择,以及更好地使用C ++的选项,是使用std :: strings而不是手动分配的C字符串。我强烈建议采用第二种方法,尽管通过第一种方法可能具有指导意义。

答案 2 :(得分:0)

来自OP:

我解决了问题:

void Parkbox::change_plate(char *s){
delete [] license_plate;
license_plate = new char[strlen(s)+1];
strcpy(license_plate, s);
}