c++ 中的默认赋值运算符=是浅拷贝吗?
只是一个简单的快速问题,我在其他地方找不到可靠的答案。默认的operator=只是右侧所有类成员的浅拷贝吗?
Class foo {
public:
int a, b, c;
};
foo f1, f2;
...
f1 = f2;
与以下内容相同:
f1.a = f2.a;
f1.b = f2.b;
f1.c = f2.c;
当我测试它时,这似乎是正确的,但我需要确保我没有错过一些特定的情况。
Just a simple quick question which I couldn't find a solid answer to anywhere else. Is the default operator= just a shallow copy of all the class' members on the right hand side?
Class foo {
public:
int a, b, c;
};
foo f1, f2;
...
f1 = f2;
would be identical to:
f1.a = f2.a;
f1.b = f2.b;
f1.c = f2.c;
This seems to be true when I test it but I need to be sure I'm not missing some specific case.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
我想说,默认
operator=
是一个副本。它复制每个成员。除非被复制的成员是某种间接的(例如指针),否则浅复制和深复制之间的区别不会出现。就默认的operator=而言,“复制”的含义取决于被复制的成员,可以是深的,也可以是浅的。
但具体来说,复制原始指针只是复制指针值,它不会对引用对象执行任何操作。因此,默认情况下,
operator=
会浅复制包含指针成员的对象。人们在编写在复制时执行克隆操作的智能指针方面做出了各种努力,因此,如果您在任何地方都使用这些指针来代替原始指针,那么默认的operator=将执行深层复制。
如果您的对象有任何标准容器作为成员,那么(例如)Java 程序员可能会感到困惑,说
operator=
是“浅拷贝”。在 Java 中,Vector
成员实际上只是一个引用,因此“浅复制”意味着Vector
成员不会被克隆:源和目标引用相同的底层向量对象。在 C++ 中,vector
成员将与其内容一起被复制,因为该成员是实际对象而不是引用(并且vector::operator= 保证内容被复制)。
如果您的数据成员是指针向量,那么您就没有深复制或浅复制。您有一个半深副本,其中源对象和目标对象具有单独的向量,但每个对象的相应向量元素仍然指向相同的未克隆对象。
I'd say, default
operator=
is a copy. It copies each member.The distinction between a shallow copy and a deep copy doesn't arise unless the members being copied are some kind of indirection such as a pointer. As far as the default
operator=
is concerned, it's up to the member being copied what "copy" means, it could be deep or shallow.Specifically, though, copying a raw pointer just copies the pointer value, it doesn't do anything with the referand. So objects containing pointer members are shallow-copied by default
operator=
.There are various efforts at writing smart pointers that perform clone operations on copying, so if you use those everywhere in place of raw pointers then the default
operator=
will perform a deep copy.If your object has any standard containers as members, then it may be confusing to (for example) a Java programmer to say that
operator=
is a "shallow copy". In Java aVector
member is really just a reference, so "shallow copy" means thatVector
members aren't cloned: source and destination refer to the same underlying vector object. In C++ avector
member will be copied, along with its contents, since the member is an actual object not a reference (andvector::operator=
guarantees the contents are copied with it).If your data member is a vector of pointers, then you don't have either a deep copy or a shallow copy. You have a semi-deep copy, where the source and destination objects have separate vectors, but the corresponding vector elements from each still point to the same, uncloned object.
是的,默认的
operator=
是浅拷贝。顺便说一句,当类具有指针作为成员时,
浅复制
和深复制
之间的实际差异就变得可见字段。在没有指针的情况下,没有区别(据我所知)!要了解它们之间的区别,请参阅以下主题(关于 stackoverflow 本身):
Yes, default
operator=
is a shallow copy.By the way, the actual difference between
shallow copy
anddeep copy
becomes visible when the class has pointers as member fields. In the absence of pointers, there is no difference (to the best of my knowledge)!To know the difference between them, see these topics (on stackoverflow itself):
“浅”与“深”复制在 C++ 中的意义不如在 C 或 Java 中的意义。
为了说明这一点,我将您的
Foo
类从三个int
更改为一个int
、一个int*
,和一个vector
:当这个程序运行时,它会产生以下输出:
int
很无聊,所以我把它省略了。但请看一下int*
和vector
之间的区别:f1 和 f2 中的int*
是相同的;这就是所谓的“浅拷贝”。然而,f1 和 f2 之间的向量
是不同的;这就是所谓的“深拷贝”。这里实际发生的情况是,C++ 中默认的
operator =
的行为就像按顺序调用其所有成员的operator =
一样。int
、int*
和其他基元类型的operator =
只是按字节浅拷贝。vector
的operator =
执行深层复制。所以我想说这个问题的答案是,不,C++ 中的默认赋值运算符不执行浅复制。但它也不执行深层复制。 C++ 中的默认赋值运算符递归地应用类成员的赋值运算符。
"shallow" versus "deep" copy is less meaningful in C++ than it is in C or Java.
To illustrate this, I've changed your
Foo
class from threeint
s to anint
, anint*
, and avector<int>
:When this program is run, it yields the following output:
The
int
is boring, so I've left it out. But look at the difference between theint*
and thevector<int>
: theint*
is the same in f1 and f2; it's what you would call a "shallow copy". Thevector<int>
however is different between f1 and f2; it's what you would call a "deep copy".What's actually happened here is that the default
operator =
in C++ behaves as if theoperator =
for all of its members were called in order. Theoperator =
forint
s,int*
s, and other primitive types is just a byte-wise shallow copy. Theoperator =
forvector<T>
performs a deep copy.So I would say the answer to the question is, No, the default assignment operator in C++ does not perform a shallow copy. But it also doesn't perform a deep copy. The default assignment operator in C++ recursively applies the assignment operators of the class's members.
是的,它只是按成员方式复制对象,这可能会导致原始指针出现问题。
Yes, it just copies the object member-wise, which can cause issues for raw pointers.
我个人喜欢加速c++中的解释。文字(第201页)说:
如果类作者没有指定赋值运算符,编译器将合成一个默认版本。默认版本被定义为递归操作 - 根据该元素类型的适当规则分配每个数据元素。每个类类型的成员都是通过调用该成员的赋值运算符来分配的。 内置类型的成员通过分配其值来分配。
由于问题中的成员是整数,我知道它们是深度复制的。您的示例的以下改编说明了这一点:
打印:
I personally like the explanation in Accelerated c++. The text (page 201) says:
If the class author does not specify the assignment operator, the compiler synthesizes a default version. The default version is defined to operate recursively - assigning each data element according to the appropriate rules for the type of that element. Each member of a class type is assigned by calling that member's assignment operator. Members that are of built-in type are assigned by assigning their values.
As the members in the question are integers, I understand that they are deep copied. The following adaptation of your example illustrates this:
which prints:
不。
operator=
根本不执行复制。它是一个赋值运算符,而不是复制运算符。默认赋值运算符对每个成员进行赋值。
No.
operator=
doesn't perform a copy at all. It's an assignment operator, not copy operator.The default assignment operator assigns each member.
如果 a、b 和 c 是类,那么将调用这些类的赋值运算符,因此编译器并不是简单地复制原始内存内容 - 但正如其他人指出的那样,将复制任何原始指针,而不会尝试复制指向的东西,从而给你悬空指针的潜力。
If a, b and c were classes then the assignment operator for those classes would be called, so the compiler isn't simply copying the raw memory contents - but as others pointed out, any raw pointers will be copied without any attempt to duplicate the pointed-to thing, thus giving you the potential for dangling pointers.
如下面的代码片段所示,STL 的 =(赋值)运算符执行深层复制。
As illustrated by the code snippet below, the = (assignment) operator for STL performs a deep copy.