提问人:bilanush 提问时间:10/10/2019 更新时间:3/17/2020 访问量:980
为什么 CPP 不创建默认的深拷贝构造函数?
Why doesn't CPP create a default deep-copy constructor?
问:
我不明白为什么他们没有一个复制构造函数来制作原始版本的真实倍数。
众所周知,默认复制构造函数的主要问题是,它执行的是浅层复制。因此,如果有指针,它只会复制它的地址,但为什么它不取消引用指针 a 复制内容? 当具有 dinamic 内存分配时会出现主要问题。这样一来,人们就可以错误地删除它,同时有一个指向它的指针,这就是为什么我们制作自己的复制构造函数并且不使用默认构造函数的原因。
但是我不明白,为什么CPP不做?为什么不复制内容
答:
众所周知,默认复制构造函数的主要问题是,它执行的是浅层复制。
我们不知道。
这就是为什么我们制作自己的复制构造函数并且不使用默认构造函数的原因。
在 C++ 中,您几乎不应该编写自己的复制构造函数(零规则)。
当具有 dinamic 内存分配时会出现主要问题。这样人们就可以错误地删除它,同时有一个指向它的指针
这不是问题。为什么?因为在C++中,我们使用了RAII的概念,并且我们在标准库中提供了解决您看到的所有问题的工具。在 C++ 中,您永远不必编写显式,也不应该有一个作为所有者的原始指针。使用标准容器(例如)和智能指针(例如()。new
std::vector
std::unique_ptr
我不明白为什么他们没有一个复制构造函数来制作原始版本的真实倍数
因为编译器不知道对象的复制语义应该是什么。只有班级的作者知道。你无法知道指针的语义是什么。是否是唯一拥有内存资源的指针?如果是这样,它是用 、 、 还是用其他东西获得的?它是否共享内存的所有权?或者它只是指向一个它不拥有的对象?由于您无法从类的声明/定义中了解其中任何内容,因此编译器根本无法使用原始指针自动实现“深度复制”。malloc
new
new[]
除非它确实如此。默认情况下,它确实实现了深拷贝,或者默认实现了浅拷贝,或者两者的组合。它这样做是正确的。还记得我告诉过你不要使用原始指针作为所有权吗?使用适当的抽象(容器、智能指针),默认的复制 ctor 将完全执行它需要做的事情。
评论
众所周知,默认复制构造函数的主要问题是,它执行的是浅层复制。
一般来说,浅拷贝不是问题。仅当要创建深层复制、具有引用成员并假定隐式复制构造函数来执行所需的操作时,这才是一个问题。
浅层复制通常是有用的,而且通常是故意的。
但是,为什么它不取消引用指针 A 复制内容呢?
因为复制构造函数将在哪里存储复制的对象?指针成员应指向何处?
编译器无法读懂您的心思,也无法知道您是要分配内存,还是如何分配内存。如果编译器确实在隐式函数中分配了内存,那么谁将负责删除它?如果编译器隐式删除了任何指针,那么当您打算使用指向不得删除的内容的非所有权指针时,这将是非常令人惊讶的。
为什么程序员不能对此负责?
内存管理已经足够困难了。目前,它至少可以通过遵循简单的规则进行管理:你的一切。如果我们引入隐式分配,并让程序员有责任知道这些隐式分配的存在,我们的工作将变得更加困难。delete
new
此外,指针可以具有无效值。在这种情况下,通过它进行间接操作将具有未定义的行为。并且无法检查指针以找出它是否无效。这将使建议的隐式“深度复制”极易出错。
浅层隐式复制是具有手动内存管理的语言中唯一明智的选择。即使在垃圾回收语言中,这通常也是更好的选择。
这就是为什么我们制作自己的复制构造函数并且不使用默认构造函数的原因。
我们很少编写用户声明的复制构造函数(初学者课程之外)。这些主要是用于管理内存(或其他资源)的类,例如智能指针。我们很少需要编写这些内容,因为标准库提供了最通用的智能指针和开箱即用的数据结构。
一旦我们在类中拥有动态内存,我们就应该创建自己的复制构造函数
事实上,如果你的类管理动态内存,那么它将需要一个自定义的复制构造函数。但典型的解决方案是不要管理类内的动态内存。见上文。将所有内存分配和其他动态资源保存在智能指针或容器中。
评论
The compiler has no way of knowing the meaning of the pointers it is supposed to "deep copy".
For example, does a float pointer point to a single float or to a C-style float array? If it is an array, what is the length of the array that it should copy? Please note that I am not talking about C++ style arrays (i.e. ).std::array
If you want "deep copying" to be handled automatically, you can use container classes for data members that should be copied.
评论