复制构造函数的用途是什么,而赋值运算符“=”也可以这样做?
为什么 C++ 提供复制构造函数?赋值运算符可以完成相同的任务。与赋值运算符相比,复制构造函数有什么优势吗?
回答
您可以使用复制构造函数执行的操作,而使用赋值运算符无法(轻松或根本无法执行):
-
复制没有默认构造函数的类。例如,如果一个类表示一个打开的文件,如果不向它传递要打开的文件名,您可能无法构造一个文件。
-
复制具有昂贵默认构造函数的类。也许构造函数分配了大量内存,然后一旦您使用赋值运算符将新状态复制到对象中,这些内存就会被释放。
-
按值传递类的实例。这就是复制构造函数的最初目的。在 C 中,如果您按值传递一个结构体,编译器只会对该结构体进行按位复制,因此接收函数有一个本地副本,它可以在不影响调用者的情况下对其进行修改。但是 C++ 认识到按位复制不是复制大多数对象的最佳方式,因此它允许您编写自己的复制构造函数(并且默认复制行为也不同,因为类成员可能具有自定义复制构造函数)。
-
复制一个包含引用的类,因为在类已经被构造之后你不能重新分配一个引用。复制构造函数和赋值运算符只是在引用方面做不同的事情。复制构造函数将引用初始化为指向正在复制的实例中引用指向的同一对象;赋值运算符实际上复制了引用对象的值。
-
复制具有 const 成员的类。(请注意,类可以具有默认构造函数,但仍然具有 const 成员。)
- Probably. I’m trying to think of an example in which you’d want to do that and not really coming up with anything.
回答
无论有没有复制构造函数,您仍然必须将新对象初始化为稳定的初始状态,然后赋值运算符可以稍后更新该状态。
虽然您当然可以在没有复制构造函数的情况下做到这一点,但拥有复制构造函数有助于优化新对象的初始化,通过将其设置为预先复制另一个对象的状态,而无需您首先将新对象初始化为默认状态,然后之后单独的分配重置该状态。这样,您可以在 1 个操作而不是 2 个操作中设置新对象的状态。