简体   繁体   English

为什么 CPP 不创建默认的深拷贝构造函数?

[英]Why doesn't CPP create a default deep-copy constructor?

I don't understand why don't they have a copy constructor which makes a real multiple of the original.我不明白为什么他们没有一个复制构造函数,它使原始的真正倍数。

As we know the main problem of the default copy constructor is, that it performs a shallow copy.我们知道默认复制构造函数的主要问题是,它执行的是浅拷贝。 So that if there is a pointer it would only copy it's address but why doesn't it dereference the pointer a copies the content?因此,如果有一个指针,它只会复制它的地址,但为什么不取消引用指针 a 复制内容? The main problem arises when having a dinamic allocation of memory.主要问题出现在动态分配 memory 时。 So that one can mistakenly delete it while having a pointer pointing to it, that's why we make our own copy constructors and do not use the default one.这样一来,当指针指向它时,可能会错误地删除它,这就是我们制作自己的复制构造函数而不使用默认构造函数的原因。

But I can't get it, why doesn't CPP do it?但是我看不懂,为什么CPP不做呢? Why doesn't it copy the content为什么不复制内容

As we know the main problem of the default copy constructor is, that it performs a shallow copy.我们知道默认复制构造函数的主要问题是,它执行的是浅拷贝。

We don't know that.我们不知道。

that's why we make our own copy constructors and do not use the default one.这就是我们制作自己的复制构造函数而不使用默认构造函数的原因。

In C++ you should almost never write your own copy constructor ( the rule of zero ).在 C++ 中,您几乎不应该编写自己的复制构造函数(零规则)。

The main problem arises when having a dinamic allocation of memory.主要问题出现在动态分配 memory 时。 So that one can mistakenly delete it while having a pointer pointing to it这样人们就可以在有一个指向它的指针时错误地删除它

It's a non-problem.这不是问题。 Why?为什么? Because in C++ we use the concept of RAII and we have tools in the standard library that solved all of the problems you see.因为在 C++ 中,我们使用了RAII的概念,并且我们在标准库中有工具可以解决您看到的所有问题。 In C++ you should never have to write explicit new and you should never have a raw pointer that is a owner.在 C++ 中,您永远不必编写显式new并且永远不应拥有作为所有者的原始指针。 Use standard containers (eg std::vector ) and smart pointers eg ( std::unique_ptr ).使用标准容器(例如std::vector )和智能指针,例如( std::unique_ptr )。

I don't understand why don't they have a copy constructor which makes a real multiple of the original我不明白为什么他们没有一个复制构造函数,它是原始的倍数

Because the compiler doesn't know what the copy-semantics of the object should be.因为编译器不知道 object 的复制语义应该是什么。 That only the writer of the class knows.只有 class 的作者知道。 You can't know what the semantics of the pointer are.你无法知道指针的语义是什么。 Is is a pointer that uniquely owns the memory resource?是唯一拥有 memory 资源的指针吗? If so, was it acquired with malloc , new , new[] , or with something else?如果是这样,它是用mallocnewnew[]还是用其他东西获得的? Does it share its ownership of the memory?它是否共享 memory 的所有权? Or is it simply pointing to an object it doesn't own?或者它只是指向它不拥有的 object? Since you cannot know any of this from the declaration/definition of a class, a compiler simply cannot implement "deep copy" automatically with raw pointers.由于您无法从 class 的声明/定义中知道任何这些,因此编译器根本无法使用原始指针自动实现“深度复制”。

Except it does .除了 It does implement deep copy by default, or shallow copy by default, or a combination of them.它默认实现深拷贝,默认实现浅拷贝,或者它们的组合。 And it does so correctly.它这样做是正确的。 Remember when I told you to not use raw pointers for ownership?还记得我告诉过你不要使用原始指针作为所有权吗? Use the appropriate abstractions (containers, smart pointers) and the default copy ctor will do exactly what it needs to do.使用适当的抽象(容器、智能指针),默认的复制 ctor 将完全完成它需要做的事情。

As we know the main problem of the default copy constructor is, that it performs a shallow copy.我们知道默认复制构造函数的主要问题是,它执行的是浅拷贝。

Shallow copying is not a problem in general.浅拷贝一般不是问题。 It's only a problem if you want to make a deep copy, have a referential member, and assume the implicit copy constructor to do what you want.如果您想进行深层复制,拥有引用成员并假设隐式复制构造函数可以执行您想要的操作,这只是一个问题。

Shallow copying is often useful and typically intentional.浅拷贝通常很有用,而且通常是有意的。

but why doesn't it dereference the pointer a copies the content?但为什么它不取消引用指针 a 复制内容?

Because where would the copy constructor store the copied object?因为复制构造函数将复制的 object 存储在哪里? Where should the pointer member point to?指针成员应该指向哪里?

The compiler cannot read your mind and cannot know whether you want to allocate memory, or how to allocate memory.编译器读不懂你的心思,也不知道你是要分配memory,还是如何分配memory。 If the compiler did allocate memory in an implicit function, then who would be responsible for its deletion?如果编译器确实在隐式 function 中分配了 memory,那么谁将负责删除它? If the compiler deleted any pointers implicitly, that would be highly surprising when you intended to have non-owning pointers to something that must not be deleted.如果编译器隐式删除了任何指针,那么当您打算拥有指向不能删除的东西的非拥有指针时,这将是非常令人惊讶的。

why can't the programmer be responsible for it?为什么程序员不能对此负责?

Memory management is difficult enough as it is. Memory 的管理已经够难了。 At the moment it is at least manageable by following the simple rule: You delete everything that you new .目前,至少可以通过遵循简单的规则进行管理: delete所有new . If we introduce implicit allocations and impose the responsibility on the programmer to know of the existence of these implicit allocations, our job would become much harder.如果我们引入隐式分配并将知道这些隐式分配存在的责任强加给程序员,我们的工作将变得更加困难。

Furthermore, a pointer can have an invalid value.此外,指针可能具有无效值。 In such cases indirecting through it would have undefined behaviour.在这种情况下,通过它间接会产生未定义的行为。 And it is impossible to inspect the pointer to find out whether it is invalid.并且无法检查指针以确定它是否无效。 This would make the suggested implicit "deep copying" highly error prone.这将使建议的隐式“深度复制”非常容易出错。

Shallow implicit copying is the only sensible choice in a language that has manual memory management.在具有手动 memory 管理的语言中,浅隐式复制是唯一明智的选择。 Even in garbage collected languages this is generally the better choice.即使在垃圾收集语言中,这通常也是更好的选择。

that's why we make our own copy constructors and do not use the default one.这就是我们制作自己的复制构造函数而不使用默认构造函数的原因。

We rarely write user declared copy constructors (outside of beginner courses).我们很少编写用户声明的复制构造函数(在初学者课程之外)。 Those are mostly needed for classes whose sole purpose is to manage memory (or other resources) such as smart pointers.这些主要用于其唯一目的是管理 memory (或其他资源)(如智能指针)的类。 And we rarely need to write those, since the standard library offers the most general smart pointers and data structures out of the box.而且我们很少需要编写这些,因为标准库提供了开箱即用的最通用的智能指针和数据结构。

we should create our own copy constructor once we have a dynamic memory inside the class一旦我们在 class 中有一个动态 memory ,我们应该创建自己的复制构造函数

Indeed, if your class manages dynamic memory, then it will need a custom copy constructor.实际上,如果您的 class 管理动态 memory,那么它将需要一个自定义复制构造函数。 But the typical solution is to not manage dynamic memory inside your class.但典型的解决方案是不在 class 内管理动态 memory。 See the paragraph above.见上段。 Keep any and all memory allocations and other dynamic resources in a smart pointer or a container.将所有 memory 分配和其他动态资源保存在智能指针或容器中。

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?例如,浮点指针是指向单个浮点数还是指向 C 样式的浮点数数组? 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 (ie std::array ).请注意,我不是在谈论 C++ 风格的 arrays (即std::array )。

If you want "deep copying" to be handled automatically, you can use container classes for data members that should be copied.如果您希望自动处理“深度复制”,您可以将容器类用于应该复制的数据成员。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM