使用复制构造函数的好处是什么?
What are the benefits of using copy constructor?
我是面向对象编程的新手,这可能是一个愚蠢的问题,但我不明白为什么如果你想创建一个对象的副本,使用类a代码比使用类B代码更好。
class A {
int num;
public:
A(const A &ref) : num(ref.num) {};
};
class B {
int num;
public:
B(B *ptToClass) : num(ptToClass->num) {};
};
如果我没记错的话,复制构造函数是在类a中使用的。
如果你不为你的类声明复制构造函数,编译器会为你声明一个。类必须具有复制构造函数。它们融入了语言,具有特殊的地位。没有它们,语言无法工作。
可能最好的例子是在按值传递时需要复制构造函数。当按值传递时,编译器将隐式调用复制构造函数。它不会调用构造函数B::B(B*)
所以,如果你希望你的类是可复制的,你应该在复制构造函数中定义复制逻辑。
类A是灵活和安全的:您可以从您拥有的任何A对象创建副本,即使它是临时的。
类B不太安全,因为可以用nullptr
调用构造函数。它不太灵活,因为您只能使用ypur构造函数来复制可以从中获取地址的对象,并且该对象不是const。
B b1(...);
const B b2(...);
B fb(); // function returning a B
B b3(&b1);
B b4(&b2); // error b2 is const
B b5(&fb()); // error you can't take adress of a temporary
问题是,如果一个构造函数被编译器认为是复制构造函数,那么它将以特殊的方式使用。例如,如果您有一个函数,它通过复制获取您的A
类型的参数,如下所示:
void function(A obj) {
// Do something with A
// ...
}
然后调用这个函数:
int main() {
A a_obj;
function(a_obj);
}
function
接收的对象obj
将由您提供的复制构造函数创建。因此,为要复制的类提供复制构造函数是一件很好的事情,这样它们就能更好地适应语言的特性和库。
在你的class B
中创建一个这样的构造函数是没有问题的,如果它适合你的应用程序的需要,但是它不会被编译器理解为复制构造函数,当编译器或库需要复制你的对象时,它不会被使用。
标准禁止在复制构造函数中使用指针:
c++标准草案n3376 -第12.8.2节:
类X的非模板构造函数是复制构造函数,如果其第一个形参类型为X&, const X&, volatile X&或者const volatileX&,或者没有其他参数,或者只有其他参数参数有默认实参
为什么复制构造函数的实参是引用而不是指针?
我认为一个更合适的问题是:何时提供用户定义的复制构造函数超过编译器提供的默认构造函数?
如我们所知,编译器提供了一个复制构造函数(默认的构造函数),用于按成员进行复制。
只要类是一个简单的具体类型(其行为在很大程度上类似于内置类型),这种按成员复制就不坏。但是对于复杂的具体类型或具有层次结构的类,按成员复制不是一个好主意,强烈建议程序员提供他自己的复制构造函数的实现(即提供用户定义的复制构造函数)。
作为一个经验法则,在类中提供用户定义的复制构造函数是个好主意。
- 文件系统:复制功能的速度秘诀是什么
- 将一种数据类型的向量复制到同一数据类型的结构向量中的有效方法是什么
- 复制文件的最佳方式是什么,以便我可以在复制过程中轻松取消复制?
- 这个奇怪的复制构造函数错误抱怨的是什么
- 从外部 VM 复制特定数据的最佳方法是什么?
- 在带有转换运算符的初始值设定项的情况下,复制列表初始化的假定行为是什么
- 有什么方法可以static_assert,模板参数是不可复制的
- 将QImage的像素复制到数组的最快方法是什么?
- 重载全常量类型的复制赋值运算符的正确方法是什么?
- 复制构造函数中出现异常的可能原因是什么
- 移动构造函数相对于复制构造函数的优势是什么?复制构造函数使用bool来表示是复制还是移动
- 复制字符串集的正确方法是什么(在复制构造函数和赋值运算符中)
- 复制包含STL成员(如vector)的C++结构的最佳方法是什么
- 让复制和直接初始化行为不同的动机是什么?
- 将 cv::Mat 向量复制到浮点数向量的最佳方法是什么?
- 使用Linux将DVD内容复制到硬盘的最快方法是什么
- std::bind 和 std::thread 总是复制参数背后的基本原理是什么?
- 将 QFile 内容复制到另一个 QFile,最佳方法是什么?
- 消除默认/删除移动/复制语义中涉及的样板的好方法是什么
- 在 C++11 中编写复制/移动/运算符 = 三重奏的"correct"方法是什么?