5

星期六我有一个考试,我正在浏览过去的论文,我遇到了根据 C++ 代码的问题:

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

第 5 行声明的目的是什么?一般来说,这种性质的声明的实现应该提供什么功能?编写在第 5 行执行声明所需的代码,因为它会出现在Car.cpp给定信息的文件中。

4

5 回答 5

9

让我们来看看这个。

从名称可以看出,这是一个构造函数。因为它需要一个参数作为对同一类型对象的引用,所以它是一个复制构造函数(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,复制时会分配新的内存来保存车牌,所以不会发生双重删除。

我更改了代码以证明这一点,但您仍然必须自己将逻辑放入其中。

于 2012-05-23T21:33:58.880 回答
8

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

我将由您决定如何最好地做到这一点。

于 2012-05-23T21:15:55.480 回答
2

这是一个复制构造函数声明。它需要一个对常量的引用Car,这意味着您可以读取传入的值,但不能(没有狡猾的强制转换)写入它。这只是通过复制原始对象来创建新对象的规范方式。您可能希望将 astrdup作为实现的一部分。

于 2012-05-23T21:16:37.770 回答
0

该声明称为复制构造函数。通常,复制构造函数用于将给定实例的新实例构造到类中。

在签名中:

Car(const Car &)

“const”意味着传递的实例不能在方法中修改。“&”表示实例通过引用传递到方法中。传入没有“&”(按值传递)的类的实例将使用复制构造函数创建该类的新实例。在声明复制构造函数的情况下,值传递不仅会自我挫败,而且会导致复制构造函数被递归调用,直到遇到堆栈溢出。

进入 cpp 文件的代码应该对传入的实例进行可接受的副本。根据用户场景,以有意义的方式接受。

于 2012-05-23T21:24:29.020 回答
-3

我假设你的意思是 5 号线,那么

Car(const Car &);

是一个构造函数,其唯一参数是对另一个 Car 对象的引用。它被标记为 const 以表明构造函数不应该修改给定的汽车。由于它是一个引用,因此您需要检查以确保您没有以某种方式引用正在构造的同一对象:

if (this==car){
  return;
}

或类似的东西。

于 2012-05-23T21:18:05.403 回答