Reputation: 23
in this code, I think it must do deep copy because I'm passing pointers, but it doesn't. I think it must print 3, but print 0. what should I do to solve this? i want to have a deep copy instead of a shallow copy.
struct node{
int number = 0;
struct node* right_child = NULL;
struct node* left_child = NULL;
};
void test(struct node* node1 , struct node* node2){
node1 = node2;
}
int main(){
struct node* a1 = new struct node;
struct node* a2 = new struct node;
a2->number = 3;
test(a1 , a2);
cout << a1->number;
}
Upvotes: 0
Views: 708
Reputation: 33952
The simple C-ish way: We ad a function that recursively clones the nodes
#include <iostream>
struct node{
int number = 0;
node* right_child = nullptr; // nullptr safer than NULL
node* left_child = nullptr;
};
node * clone(const node * src){
if (src) { // there is a node. Copy it.
return new node{src->number,
clone(src->right_child), // clone right
clone(src->left_child)}; // clone left
}
else { // no node. Nothing to do and end the branch
return nullptr;
}
}
void test(node*& node1, // reference to pointer
node* node2){
delete node1; // Free storage currently used by node1
// But what of the nodes that could be in its tree?
// Think on this. Ask another question if necessary.
// this is where the simple way starts to fall down
node1 = clone(node2);
}
int main(){
struct node* a1 = new node; // wasted memory. We're about to replace it.
// need a more complicated tree to prove deep copy works
struct node* a2 = new node{3,
new node{4, nullptr, nullptr}, // a right node
nullptr}; // no left node
// a2->number = 3; done above now
test(a1 , a2);
std::cout << a1->number << ' '
<< a1->right_child->number;
delete a1; // clean up
delete a2;
}
More complicated canonical C++ way using The Rule Of Three and The Copy and Swap Idiom
#include <iostream>
#include <algorithm> // for std::swap
struct node{
int number = 0;
node* right_child = nullptr; // nullptr safer than NULL
node* left_child = nullptr;
static node * clone(node * src)
{
if (src)
{
return new node(*src);
}
return nullptr;
}
// generic constructor
node(int number = 0,
node* right_child = nullptr,
node* left_child = nullptr):
number(number),
right_child(right_child),
left_child(left_child)
{
}
//copy constructor
node (const node & src):
number(src.number),
right_child(clone(src.right_child)),
left_child(clone(src.left_child))
{
}
// assignment operator via copy and swap.
node & operator=(node src)
{
std::swap(number, src.number);
std::swap(right_child, src.right_child);
std::swap(left_child, src.left_child);
return *this;
}
// destructor
~node()
{
delete right_child;
delete left_child;
}
};
void test(node* node1,
node* node2){
*node1 = *node2; // now, thanks to all of the infrastructure above, we can
// assign nodes with the dumb old = operator. All we have to do
// is dereference the pointers.
}
int main(){
struct node* a1 = new node; // wasted memory. We're about to replace it.
// need a more complicated tree to prove deep copy works
struct node* a2 = new node{3,
new node{4, nullptr, nullptr}, // a right node
nullptr}; // no left node
// a2->number = 3; done above now
test(a1 , a2);
std::cout << a1->number << ' '
<< a1->right_child->number;
delete a1; // clean up
delete a2;
}
All of the nodes are now self-managing.
But, my opinion, the nodes should be kept as dumb as they are in the simple example. They shouldn't need to know about the tree at all. Knowledge of the tree should be in a Tree
class that uses the nodes as simple containers. The Tree
class should do all of the management of the nodes--creating, copying, cloning, deleting--because only it knows everything necessary to represent the tree. The users of the tree shouldn't even know nodes exist. They put data into the tree, take data out of the tree, and observe the tree without caring how the tree works and being able to so something stupid like
delete a_node;
and blow the crap out of data the tree isn't done with yet.
The Tree
class preferably works iteratively rather than recursively so that the trees can be arbitrarily sized. Unless you're really careful recursing through a large tree to clone it, delete it, display it, or pretty much anything else you do with a tree runs the risk of exhausting automatic storage and causing what's typically called a Stack Overflow.
Upvotes: 0
Reputation: 101
just use
void test(struct node *node1, struct node *node2) { *node1 = *node2; }
instead of
void test(struct node *node1, struct node *node2) { node1 = node2; }
and it will print 3.
when you do node1 = node2;
int the test1, you assign the pointer itself, not the structure pointed to by the pointer.When the function ends, the parameters node1
and node2
will be destroyed, so you have done nothing...
Upvotes: -1