Writing Copy Constructor & Assignment Operator Methods

Apr 26, 2012 at 6:10am
I'm just wondering how you would write an assignment operator and copy constructor methods. This has been a big sticking point for me. I know that when you do something like

1
2
3
4
 node * head = NULL;
// some form of making nodes that connect, blah blah blah.
node * temp = head;


You can't just assume that when you copy that you're getting everything. And by this, I mean you need to overload the assignment operator so that it will do a deep copy. I'm having trouble writing it. I think it would be easy to do it recursively. Pass in the head node, and check for NULL. If its not NULL, call the method again, until you hit NULL. Also making sure you copy when its not NULL. Any help?
Apr 26, 2012 at 8:19am
Well the copy constructor or overloaded operator would do the same job here, really, so take your pick.

In either, you'll just need to pass in a node as a parameter, then assign each of the values of the node accordingly.

I'm not at a compiler or anything right now, but I guess the syntax would be something like this:
1
2
3
4
5
node::node(const node& n)
{
   this->data = n.data;
   this->other_data = n.other_data;
}


If you want to avoid copying a NULL node, just enclose the functionality above in a check:
1
2
3
4
5
6
7
8
node::node(const node& n)
{
   if( n != NULL)
   {
      this->data = n.data;
      this->other_data = n.other_data;
   }
}


Again, syntax might be off, but hopefully you get the gist.
Last edited on Apr 26, 2012 at 8:21am
Apr 26, 2012 at 10:23am
making assumptions about the rest of your class (it would have helped if you posted it), sounds like you'r looking for something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
template<typename T>
struct Node {
    Node* head;
    T data;
    Node(const T& data) : head(nullptr), data(data) {}
    Node(const Node& n) : head(n.head ? new Node(*n.head) : n.head), data(n.data) {}
    Node& operator=(Node n) { 
            std::swap(head, n.head); 
            std::swap(data, n.data); 
            return *this; 
    }
    ~Node() { delete head; }
};

but you may consider better pointers, too, such as std::unique_ptr
Last edited on Apr 26, 2012 at 10:27am
Apr 26, 2012 at 12:21pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <string>
using namespace std;

#ifndef ORDEREDH
#define ORDEREDH

class node
{
public:

	double data;
	node * next;
	
	node() {next = NULL;}
	node( double value ) { data = value; next = NULL; }
	
};

class LinkedList
{
public:
	LinkedList() { head = NULL; }
	//~LinkedList();
	LinkedList( const LinkedList &other );
	LinkedList& operator=(const LinkedList & rhs);

	void Insert( double value );
	bool RemoveByVal( double value );
	bool RemoveByPos( int pos );
	void Print();
	bool Find( double value );

	// unused
	void Append( double value );
private:
	node * head;
};

#endif  


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include "ordered.h"

LinkedList::LinkedList( const LinkedList &other ) // does not work
{
	if(other.head == NULL)
		return;
	
}

LinkedList& LinkedList::operator=(const LinkedList & rhs) // does not work
{
	if(rhs.head == NULL)
		return *this;
	
	return *this;	
}

// missing the destructor

void
LinkedList::Append( double value )
{
	if( head == NULL )
	{
		head = new node( value );
		return;
	}
	node * current = head;
	while( current->next != NULL) 
	{
		current = current->next;
	}
	current->next = new node(value);
}

void
LinkedList::Insert( double value )
{
	node * temp = new node( value );

	// condition for empty list
	if( head == NULL )
	{
		node * temp = new node( value );
		temp->next = head;
		head = temp;
		return;
	}

	// condition to put the new item before the first item
	if(temp->data < head->data)
	{
		temp->next = head;
		head = temp;
		return;
	}
	//initial traversal to correct position in list
	node * current = head;
	while( (current->data < temp->data) && (current->next != NULL) )
	{
		current = current->next;
	}
	
	// changes to put new item in the list
	temp->next = current->next;
	current->next = temp;
	return;
}

void
LinkedList::Print()
{
	node * current = head;
	while( current != NULL )
	{
		cout << current->data << endl;
		current = current->next;
	}
	cout << endl;
}

bool 
LinkedList::Find( double value )
{
	node * current = head;
	int count = 1;
	while( current != NULL )
	{
		if( value == current->data )
		{
			cout << "Found at position " << count << endl;
			return true;
		}
		current = current->next;
		count++;
	}
	cout << "No such value, '" << value << "'" << endl;

	return false;
	
}

bool
LinkedList::RemoveByVal( double value )
{
	node * temp = NULL;
	// used if first element has value to be removed
	if(head->data == value)
	{
		temp = head->next;
		head = temp;
		cout << value << " was removed. " << endl;
		Print();
		return true;
	}

	//initial traversal to correct position in list
	node * current = head;

	while( (current->data != value) && (current->next != NULL) )
	{
		if(current->next->data != value)
		{
			current = current->next;
		}
		else
		{
			temp = current->next->next;
			current->next = temp;
			//delete temp;
			cout << value << " was removed. " << endl;
			Print();
			return true;
		}
	}	
	cout << value << " wasn't in the list. " << endl;
	return false;

}

bool
LinkedList::RemoveByPos( int pos )
{
	//initial traversal to correct position in list
	node *current = head;
	int ct = 1;
	while( (ct < pos - 1) && (current->next != NULL))
	{
		current = current->next;
	}
	return false;
} 
Apr 26, 2012 at 1:30pm
Yes, the usual copy and assignment work for you:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class node
{
public:
    double data;
    node * next;

    node() : next(NULL) {} // I don't think default ctor makes sense, actually
    node( double value ) : data(value), next(NULL) {}
    node( const node& n) : data(n.data),
                           next(n.next ?  new node(*n.next) : NULL)  {}
    node& operator=(node n) { 
            std::swap(next, n.next); 
            std::swap(data, n.data); 
            return *this; 
    }
    ~node() { delete next; }
};


(remember to #include <utility> or #include <algorithm> to get std::swap)

How did you write such a big program without completing the node class, though? Consider testing the components you write before combining them into a larger program.
Last edited on Apr 26, 2012 at 1:37pm
Apr 26, 2012 at 11:36pm
I was told you shouldn't create a destructor in the node class because its not allocating memory. I was told that I should create a destructor for my linked list class instead.
Apr 26, 2012 at 11:37pm
Also I was referring to the copy, assignment, and destructor methods for my linked list class, not the node class.
Apr 27, 2012 at 8:14am
Topic archived. No new replies allowed.