如果类成员是向量,我们是不是应该显式编写复制构造函数?
Posted
技术标签:
【中文标题】如果类成员是向量,我们是不是应该显式编写复制构造函数?【英文标题】:Should we explicitly write a copy constructor if the class member is a vector?如果类成员是向量,我们是否应该显式编写复制构造函数? 【发布时间】:2012-01-25 09:52:06 【问题描述】:struct myType
vector<char*> ls;
;
这里ls
持有指向char
的指针。如果没有为myType
提供用户定义的复制构造函数,myType
的默认复制构造函数是否会对ls
进行深层复制?
【问题讨论】:
我的意思是说vector是否持有任何指向原始或用户定义数据类型的指针(指向类的指针) 【参考方案1】:这里 ls 持有指向 char 的指针。如果没有提供拷贝构造函数,默认拷贝构造函数会做深拷贝吗?
默认的复制构造函数将复制所有成员——即调用它们各自的复制构造函数。1所以是的,std::vector
(就 C++ 而言没什么特别的)将被适当地复制。
但是,向量内的char*
元素指向的内存当然不会,因为 C++ 不知道也不关心指针指向什么。
但这里的解决方案不是提供自定义复制构造函数。这是使用数据结构 而不是原始指针 (char*
)。这恰好是std::string
(或std::vector<char>
,具体取决于意图)。
1 从而创建一个复制操作的传递闭包——这就是深度复制通常的实现方式,当然复制操作的实现者总是可以突破。
【讨论】:
“这是对“深拷贝”的一个很好的定义”——如果这是对“深拷贝”的一个很好的定义,那么“浅拷贝”会是什么样子?我个人认为这是一个“副本”。当且仅当人们将vector
的元素视为某种形式的间接时,术语“深拷贝”和“浅拷贝”才有意义。如果有人这样做,那么这是一个“浅拷贝”,但正如你所说的 vector
不在乎它的元素是指针还是其他任何东西。
@Steve 根据复制构造的语言机制,恕我直言,区别仅对指针/引用分配有意义。但是由于 ctor 是 C++ 定义复制操作的方式,并且由于调用 one ctor 对其所有成员执行此复制操作的传递闭包,因此调用它没有任何意义,除非深度复制,恕我直言。如果你没有在闭包层次结构中提供复制语义(通过使用原始指针而不通过封装将其与复制语义相关联),那么你明确告诉 C++ 放弃它的复制机制。
只是关于措辞的一点点:向量内的char*
元素肯定是被复制的。没有复制的是他们指向的东西。 (我很确定这就是你的意思。)
将其称为深拷贝是错误的。严格地说它是什么:成员复制。这是深拷贝还是浅拷贝在很大程度上取决于数据的结构。说这是一个深拷贝也意味着复制一个指针(而不是引用的对象)将是一个深拷贝。
@edA-qa mort-ora-y:同意,根据 Konrad 的定义,char *a = 0; char *b = a;
是一个深层副本,并且“将其称为其他任何东西都没有意义”。特别是,将其称为“副本”是没有意义的,这就是标准所称的(在这种情况下是副本分配)。所以我不能接受康拉德的术语,我希望其他人也不接受。我喜欢“成员复制”这个术语——每个成员都被复制,我们都知道复制指针意味着什么。涉及指针的“深度复制”似乎是有争议的——我认为这意味着复制引用,康拉德认为它没有。【参考方案2】:
默认的拷贝构造函数会做深拷贝吗?
当然不是。编译器无法知道谁拥有指向的内存。
如果需要深拷贝,则必须实现复制构造函数,并手动将每个char*
复制到新内存中,用于复制到object
中的vector
。
如果您将char*
用作以零结尾的字符串,那么您应该真正改用std::string
。如果这样做,默认构造函数就足够了。
【讨论】:
【参考方案3】:不,不会。
C++ 会递归调用所有子对象的拷贝ctor。因此它将调用向量的复制 ctor,进而调用 char*
的复制 ctor,后者将按值复制 char*
。 C++ 永远不会自动分配内存和复制数据。它甚至不可能这样做,因为它不知道您指向的数据是什么,以及它应该复制多少。
当您使用字符串时,您应该更喜欢使用std::string
,因为它会为您完成所有的复制工作。如果它是一些需要特殊处理的二进制数据缓冲区,那么您需要自己在复制 ctor 中执行此操作(完成后,请考虑一下考虑要求 C++ 为您执行此操作是否真的明智) .
当您编写自己的复制 ctor 时,您应该始终注意 Rule of Three
【讨论】:
以上是关于如果类成员是向量,我们是不是应该显式编写复制构造函数?的主要内容,如果未能解决你的问题,请参考以下文章
私有成员是不是应该在惯用的 C# 中显式声明为私有? [关闭]
C++中的派生类,可以不定义对象直接调用基类的成员和调用自己的成员函数嘛???