星期六我有一个考试,我正在浏览过去的论文,我遇到了根据 C++ 代码的问题:
class Car {
char *LicencePlate;
int age;
public:
Car(const Car &); //this declaration
~Car();
}
第 5 行声明的目的是什么?一般来说,这种性质的声明的实现应该提供什么功能?编写在第 5 行执行声明所需的代码,因为它会出现在Car.cpp
给定信息的文件中。
星期六我有一个考试,我正在浏览过去的论文,我遇到了根据 C++ 代码的问题:
class Car {
char *LicencePlate;
int age;
public:
Car(const Car &); //this declaration
~Car();
}
第 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;
}
};
我已经修改了你的课程以便更好地解释。你的班级现在管理记忆。它为LicencePlate
. 这是您没有复制构造函数的场景。说你这样做:
Car a("abc",3);
编译器生成的复制构造函数被调用:
Car b(a);
但请记住,这只是一个浅拷贝。所以,实际上,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;
}
};
三规则意味着您应该实现一个赋值运算符(您已经有一个复制构造函数和一个析构函数)。这背后的动机是相同的,只有当您分配而不是初始化时问题才会复制:
Car a("abc",3);
Car b;
b = a; //assignment - operator= is called
现在我们安全了。b
,复制时会分配新的内存来保存车牌,所以不会发生双重删除。
我更改了代码以证明这一点,但您仍然必须自己将逻辑放入其中。
它是一个复制构造函数,其目的是制作作为参数给出的对象的精确副本。
我将由您决定如何最好地做到这一点。
这是一个复制构造函数声明。它需要一个对常量的引用Car
,这意味着您可以读取传入的值,但不能(没有狡猾的强制转换)写入它。这只是通过复制原始对象来创建新对象的规范方式。您可能希望将 astrdup
作为实现的一部分。
该声明称为复制构造函数。通常,复制构造函数用于将给定实例的新实例构造到类中。
在签名中:
Car(const Car &)
“const”意味着传递的实例不能在方法中修改。“&”表示实例通过引用传递到方法中。传入没有“&”(按值传递)的类的实例将使用复制构造函数创建该类的新实例。在声明复制构造函数的情况下,值传递不仅会自我挫败,而且会导致复制构造函数被递归调用,直到遇到堆栈溢出。
进入 cpp 文件的代码应该对传入的实例进行可接受的副本。根据用户场景,以有意义的方式接受。
我假设你的意思是 5 号线,那么
Car(const Car &);
是一个构造函数,其唯一参数是对另一个 Car 对象的引用。它被标记为 const 以表明构造函数不应该修改给定的汽车。由于它是一个引用,因此您需要检查以确保您没有以某种方式引用正在构造的同一对象:
if (this==car){
return;
}
或类似的东西。