C++类中的奇怪构造函数

Kas*_*łek 5 c++ constructor class

星期六我参加了考试,我正在阅读过去的论文,我根据C++代码遇到了问题:

class Car {
     char *LicencePlate;
     int age;
public:
     Car(const Car &); //this declaration
     ~Car();
}
Run Code Online (Sandbox Code Playgroud)

第5行声明的目的是什么?一般来说,实施这种性质的声明应该提供哪些功能?在第5行写下声明实现所需的代码,就像在Car.cpp提供的信息中出现在文件中一样.

Luc*_*ore 9

我们来看看吧.

从名称可以看出,这是一个构造函数.因为它需要一个参数引用相同类型的对象,所以它是一个复制构造函数(C++命名法).

如您所知(或不知道),如果您没有复制构造函数,编译器将为您生成一个.编译器生成的复制构造函数执行浅复制.

为什么要实现自己的:

class Car {
     char *LicencePlate;
public:
     Car(char* plate, int size)
     {
        LicencePlate = new char[size];
        strcpy(LicencePlate, plate);
     }
     ~Car()
     {
        delete[] LicencePlate;
     }
};
Run Code Online (Sandbox Code Playgroud)

我已经修改了你的课程以便更好地解释.你的班级现在管理记忆.它为内存分配LicencePlate.这是您没有复制构造函数的情况.说你做:

Car a("abc",3);
Run Code Online (Sandbox Code Playgroud)

编译器生成的拷贝构造函数被调用:

Car b(a);
Run Code Online (Sandbox Code Playgroud)

但请记住,这只是一个浅拷贝.所以,实际上,a.LicencePlate == b.LicencePlate.你能看到什么问题吗?

如果a超出范围,析构函数被调用,并且a.LicencePlate被删除.但是当b你超出范围时你会遇到未定义的行为,因为b析构函数会尝试删除相同的内存(记住,两个指针指向同一个内存,因为创建了一个浅的副本).

为避免这种情况,您可以定义自己的复制构造函数:

class Car {
     char *LicencePlate;
     int sz;
public:
     Car(char* plate, int size)
     {
        LicencePlate = new char[size+1]();
        strcpy(LicencePlate, plate);
        sz = size;
     }
     Car(const Car& other)
     {
        LicencePlate = new char[other.sz+1]();
        sz = other.sz;
        strcpy(LicencePlate, other.LicencePlate);
     }
     ~Car()
     {
        delete[] LicencePlate;
     }
};
Run Code Online (Sandbox Code Playgroud)

规则三意味着你应该实现一个赋值运算符(你已经有一个复制构造函数和一个析构函数).这背后的动机是相同的,只有当您分配而不是初始化时问题会复制:

Car a("abc",3);
Car b;
b = a; //assignment - operator= is called
Run Code Online (Sandbox Code Playgroud)

现在我们很安全.b,复制时,将分配新的内存来保存车牌,因此不能进行双重删除.

我更改了代码以证明这一点,但你仍然必须自己将逻辑放在那里.

  • 啊,三个规则,通常表示为"使用`std :: string LicencePlate;`而不是虚拟!". (3认同)

Ben*_*Ben 8

它是一个复制构造函数,它的目的是制作作为参数给出的对象的精确副本.

我会留给你决定如何最好地做到这一点.