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提供的信息中出现在文件中一样.
我们来看看吧.
从名称可以看出,这是一个构造函数.因为它需要一个参数引用相同类型的对象,所以它是一个复制构造函数(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,复制时,将分配新的内存来保存车牌,因此不能进行双重删除.
我更改了代码以证明这一点,但你仍然必须自己将逻辑放在那里.