提问人:Jay 提问时间:1/19/2020 更新时间:1/19/2020 访问量:104
实现对象指针的复制构造函数和运算符的正确方法是什么
What is the proper way to implement a copy constructor and operator for object pointers
问:
我试图为 Next 和 Prev 对象指针执行复制构造函数和赋值运算符,但是,当它尝试复制时,我没有得到正确的数据。我不确定这是否实施错误。
Node.cpp
Node::Node(const Node& h)
{
Next = new Node(*h.Next);
Prev = new Node(*h.Prev);
data = h.data;
}
Node::~Node()
{
delete Next;
delete Prev;
}
Node& Node::operator=(const Node& t)
{
delete Next;
delete Prev;
Next = new Node(*t.Next);
Prev = new Node(*t.Prev);
data = t.data;
return *this;
}
Node.H
Private:
Node* Next;
Node* Prev;
int data;
答:
不应具有 的复制构造函数。创建节点的副本是没有意义的。Node
节点是列表的元素。副本是否应该是同一列表中的重复节点?但是在列表中的哪个位置?在头上?最后?一开始?这毫无意义。
制作副本应该是不同列表中的重复节点吗?但是在什么列表中?同样,这毫无意义。
为什么你认为你的类应该有一个复制构造函数?你认为它应该做什么?Node
如果你有答案,那么创建一个复制构造函数。如果你不这样做,就不要。
同样的逻辑也适用于赋值运算符。它应该做什么?没有明显的答案。因此,除非你对它应该做什么有一个准确的想法,否则不要写它。
评论
Node::~Node() { delete Next; delete Prev; }
当一个节点被销毁时,它会销毁它的后继节点。这反过来又摧毁了它的前任,摧毁了它的继任者,摧毁了它的前任,它摧毁了......你能发现问题吗?这种递归是无限的。它永无止境。此外,行为是未定义的,因为您删除了已删除的指针值。通常,列表操作只进行一种方式。你不需要回去,因为那是算法“来自”的地方。
即使我们通过不双向来解决问题,递归的另一个问题是它与列表的长度一样深。鉴于大多数系统通常具有有限的调用堆栈大小,这会对列表的最大大小施加隐式限制。通常,链表操作应使用迭代而不是递归。
这两个问题都发生在所有显示的函数中。
我没有尝试在课堂上执行深度复制。
那么你就犯了一个错误,因为你的复制构造函数和赋值运算符执行了深度复制 - 或者至少它们看起来像是深度复制的损坏版本。
如果你想要浅拷贝,那么你就需要隐式生成的操作。如果你确实想要浅拷贝,那么你也应该希望指针是非所有权的,因此也希望使用隐式析构函数。
评论
Node
Node