提问人:Vendor 提问时间:9/10/2021 最后编辑:Adrian MoleVendor 更新时间:9/15/2021 访问量:681
包含指向指针的对象的深层复制
Deep Copy of an Object that contains a Pointer to Pointers
问:
我正在尝试为包含指针的对象制作一个复制构造函数,该指针引用其他指针等。 下面的代码是一个二叉树。
BTree.h
{
public:
vertex* root;
BTree()
{
root = NULL;
};
~BTree() {
delete root;
root = nullptr;
};
BTree(const BTree& p_BTree) //copy constructor
{
root = new vertex(*p_BTree.root);
}
BTree& operator= (const BTree& other) //assignment operator
{
// Delete the existing class A instance
delete root;
// and create a new as a copy of other.attribute
root = new vertex(*other.root);
}
节点.h
class vertex{
public:
int key;
string data;
vertex* leftChild;
vertex* rightChild;
vertex* parent;
int height;
vertex(string data){
key = ID;
this->data = data;
leftChild = NULL;
rightChild = NULL;
parent = NULL;
ID++;
};
vertex(){
key = 0;
leftChild = NULL;
rightChild = NULL;
parent = NULL;
};
vertex(vertex* node){
key = ID;
leftChild = node->leftChild;
rightChild = node->rightChild;
parent = node->parent;
};
~vertex(){
delete leftChild;
delete rightChild;
leftChild = nullptr;
rightChild = nullptr;
};
void print(string indent){
string indent2 = indent;
cout <<indent << " " << data <<endl;
if(leftChild != nullptr || rightChild != nullptr)
{
if(leftChild != nullptr){
indent = "|" + indent;
leftChild->print(indent);
}else{
cout << indent << endl;
}
if(rightChild != nullptr){
indent2 = "|" + indent2;
rightChild->print(indent2);
}else{
cout << indent2 << endl;
}
}
}
};
#include "BTree.h"
int main() {
// Aufgabe 1
BTree B;
B.main();
// Aufgabe 2
BTree C = B; //Call copy constructor
C.print();
// Aufgabe 3
BST D;
D.main();
D.print(D.root);
D.sortvector(); //neu hinzugefügt
// Aufgabe 4
D.PrintLayers(D.root, 1);
}
问题在于,当调用析构函数时,程序会崩溃,因为它试图释放已释放的内存。
对象 B 和 C(在 main 中)中的根具有不同的内存地址,问题是对象 C 中的 leftchilds 和 rightchilds。这些是浅层的,而不是深层的。我不知道如何在这些属性的复制构造函数中执行此操作。
这是它在调试器中的样子:
答:
0赞
t.niese
9/10/2021
#1
我没有时间检查你的完整代码。
但是,如果 .root = new vertex(*p_BTree.root);
root
nullptr
而你管理资源(它在析构函数中有一个),但不遵循三/五的规则。vertex
delete
因此,一旦创建了 的实例的副本,指针就会被复制,并且两个实例管理相同的指针,这会导致双重释放。vertex
vertex
在树的节点中使用它是有问题的:
~vertex(){
delete leftChild;
delete rightChild;
leftChild = nullptr;
rightChild = nullptr;
};
如果你有一棵树的深度很大,你可能会遇到堆栈溢出。原因是删除是递归完成的。您希望在根目录中收集树的节点并在那里删除它们。
对于必须为 创建的复制构造函数和复制分配运算符中的深度复制也是如此。vertex
更多说明:
- 在析构函数之后执行操作是您不需要做的事情。与 .
root = nullptr;
delete
vertex
- 保持一致,不要混用和 .你应该坚持使用.
NULL
nullptr
nullptr
root = NULL;
在构造函数中,应使用成员变量的默认值或通过构造函数的成员初始值设定项列表完成。与 .vertex
下一个:复制对象(无堆)
评论
vertex
std::unique_ptr