包含指向指针的指针的 Object 的深层副本
Deep Copy of an Object that contains a Pointer to Pointers
我正在尝试为包含指针的 Object 创建一个复制构造函数,该指针引用其他指针等。
下面的代码是一个二叉树。
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);
}
Node.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);
}
问题是当调用析构函数时,程序崩溃,因为它试图释放已经释放的内存。
ObjectB 和 C 中的根(在 main 中)具有不同的内存地址,问题是 ObjectC 中的左孩子和右孩子。这些复制浅而不深。我不知道如何在这些属性的复制构造函数中执行此操作。
这是它在调试器中的样子:
我没有时间检查你的完整代码。
但是如果 root
是 nullptr
,那么复制构造函数中的 root = new vertex(*p_BTree.root);
就会有问题。
而你的vertex
管理资源(它在析构函数中有一个delete
),但不遵循three/five的规则。
因此,一旦创建了 vertex
实例的副本,就会复制指针,并且 vertex
的两个实例管理相同的指针,这会导致双重释放。
并且在树的节点中使用它是有问题的:
~vertex(){
delete leftChild;
delete rightChild;
leftChild = nullptr;
rightChild = nullptr;
};
如果你有一棵深度很大的树,你可能会遇到 Whosebug。这样做的原因是因为删除是递归完成的。您想收集根中树的节点并在那里删除它们。
你必须为vertex
创建的复制构造函数和复制赋值运算符中的深度复制也是如此。
补充说明:
- 在析构函数中
delete
之后执行 root = nullptr;
是您不需要做的事情。 vertex
. 相同
- 保持一致,不要混淆
NULL
和 nullptr
。你应该坚持 nullptr
.
构造函数中的 root = NULL;
应该使用成员变量的默认值或通过构造函数的成员初始值设定项列表来完成。 vertex
. 相同
我正在尝试为包含指针的 Object 创建一个复制构造函数,该指针引用其他指针等。 下面的代码是一个二叉树。
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);
}
Node.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);
}
问题是当调用析构函数时,程序崩溃,因为它试图释放已经释放的内存。
ObjectB 和 C 中的根(在 main 中)具有不同的内存地址,问题是 ObjectC 中的左孩子和右孩子。这些复制浅而不深。我不知道如何在这些属性的复制构造函数中执行此操作。
这是它在调试器中的样子:
我没有时间检查你的完整代码。
但是如果 root
是 nullptr
,那么复制构造函数中的 root = new vertex(*p_BTree.root);
就会有问题。
而你的vertex
管理资源(它在析构函数中有一个delete
),但不遵循three/five的规则。
因此,一旦创建了 vertex
实例的副本,就会复制指针,并且 vertex
的两个实例管理相同的指针,这会导致双重释放。
并且在树的节点中使用它是有问题的:
~vertex(){
delete leftChild;
delete rightChild;
leftChild = nullptr;
rightChild = nullptr;
};
如果你有一棵深度很大的树,你可能会遇到 Whosebug。这样做的原因是因为删除是递归完成的。您想收集根中树的节点并在那里删除它们。
你必须为vertex
创建的复制构造函数和复制赋值运算符中的深度复制也是如此。
补充说明:
- 在析构函数中
delete
之后执行root = nullptr;
是您不需要做的事情。vertex
. 相同
- 保持一致,不要混淆
NULL
和nullptr
。你应该坚持nullptr
.
构造函数中的 root = NULL;
应该使用成员变量的默认值或通过构造函数的成员初始值设定项列表来完成。vertex
. 相同