Deep Copying implementation

Hello,

I apologize in advance if there is something wrong in this post. I just registered and just read the rules. I am trying my best to follow them. If this post goes against the rules or if found offensive in any way please delete it.

OK I will be honest, this is a homework question (I am not asking you to do it for me, I am paying for this course, therefore I want to learn) and we had to build a list based on pointers and references, now I have to do the following.

Using the list class we developed in class, make the following modifications:

1) Change the data member in the Node class to a std::string variable.

2) Make the return types for the data getters in both List and Node classes
const references. Make the arguments for the Node ctor and the List data
setters const references.
3) Implement a copy ctor and assignment operator with deep copy on both the List
and Node classes so that using these function does not end up with an
inglorious crash.

Now I am not asking to do my homework, (otherwise what would be the point of paying for a C++ course) I want to learn C++ and be able to do it myself, I am having problems implementing the deep copy and assignment operator and I tried on my own, but so far I am getting the following errors and warnings

c:\code\cpp\assigment8\node.h(27) : warning C4172: returning address of local va
riable or temporary
c:\code\cpp\assigment8\node.h(29) : warning C4172: returning address of local va
riable or temporary
list.cpp
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\xlocale(323) : wa
rning C4530: C++ exception handler used, but unwind semantics are not enabled. S
pecify /EHsc
c:\code\cpp\assigment8\node.h(27) : warning C4172: returning address of local va
riable or temporary
c:\code\cpp\assigment8\node.h(29) : warning C4172: returning address of local va
riable or temporary
list.cpp(21) : error C2664: 'Node::Node(const std::string)' : cannot convert par
ameter 1 from 'int' to 'const std::string'
        No constructor could take the source type, or constructor overload resol
ution was ambiguous
list.cpp(38) : error C2664: 'Node::Node(const std::string)' : cannot convert par
ameter 1 from 'int' to 'const std::string'
        No constructor could take the source type, or constructor overload resol
ution was ambiguous
list.cpp(106) : error C2440: 'return' : cannot convert from 'const std::string'
to 'int'
        No user-defined-conversion operator available that can perform this conv
ersion, or the operator cannot be called
list.cpp(117) : error C2440: 'return' : cannot convert from 'const std::string'
to 'int'
        No user-defined-conversion operator available that can perform this conv
ersion, or the operator cannot be called


Again, I don't want you to do my homework for me, I want you to guide me through it, so I can do it myself.

Now This is a multiple file program and if you don't mind I will post code for each file below

list_test.cpp

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
#include <iostream>
#include "list.h"

using std::cout;
using std::endl;
    
int main()
{
    
    List ls;
    ls.PushFront(4);
    ls.PushFront(6);
    ls.PushFront(8);
    ls.PushFront(10);
    ls.PushFront(-3);
    ls.PushFront(-7);

    //Testing the copy ctor
    {
        List lsTemp(ls);
    }    

    cout << "Testing  Front operations: " << endl;     
    while(ls.IsEmpty() == false)
    {
        cout << ls.Front() << " ";
        ls.PopFront();
    }
    
    
    ls.PushBack(4);
    ls.PushBack(6);
    ls.PushBack(8);
    ls.PushBack(10);
    ls.PushBack(-3);
    ls.PushBack(-7);
    
    //Testing the assignment operator
    {
        List lsTemp;
        lsTemp = ls;
    }    


    cout << "\nTesting  Back operations: " << endl ;    
    while(ls.IsEmpty() == false)
    {
        cout << ls.Back() << " ";
        ls.PopBack();
    }   
    return 0;
}        



list.cpp

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
#include "list.h"


List::List(): _phead(0), _ptail(0)
{
}


List::~List()
{
    Clear();
}

bool List::IsEmpty() const
{
    return (_phead == 0);
}    

void List::PushFront(int data)
{
    Node* pNode = new Node(data);
    
    if(_ptail == 0)
    {
        _phead = pNode;
        _ptail = pNode;
    }
    else
    {
        _phead -> _pprev = pNode;
        pNode -> _pnext = _phead;
        _phead = pNode;        
    }
}

void List::PushBack(int data)
{
    Node* pNode = new Node(data);
    
    if(_ptail == 0)
    {
        _phead = pNode;
        _ptail = pNode;
    }
    else
    {
        _ptail -> _pnext = pNode;
        pNode -> _pprev = _ptail;
        _ptail = pNode;        
    }
}

void List::PopFront()
{
    if(IsEmpty())
    {
       
        return;
    }
    if(_phead == _ptail)
    {
        //Only one item in the list
        delete _phead;
        _phead = 0;
        _ptail = 0;
    }
    else
    {
        Node* pNode = _phead;
        _phead = _phead -> _pnext;
        _phead -> _pprev = 0;
        delete pNode;
    }
}

void List::PopBack()
{
    if(IsEmpty())
    {
       
        return;
    }
    if(_phead == _ptail)
    {
        //Only one item in the list
        delete _phead;
        _phead = 0;
        _ptail = 0;
    }
    else
    {
        Node* pNode = _ptail;
        _ptail = _ptail -> _pprev;
        _ptail -> _pnext = 0;
        delete pNode;
    }
}

int List::Front() const
{
    if(IsEmpty())
    {
        
        return 0;
    }
    return _phead -> _data;
    
}

int List::Back() const
{
    if(IsEmpty())
    {
        
        return 0;
    }
    return _ptail -> _data;
}

unsigned List::Count() const
{
    if(IsEmpty())
    {
        return 0;
    }    
    
    return _phead -> Count();
}

void List::Clear()
{
    if(IsEmpty())
    {
        return;
    }    
    
   
    while(!IsEmpty())
    {
        PopFront();
    }   
}


node.h
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
#if !defined (NODE_H__)
#define NODE_H__

#include <string>

using std::string;
class Node
{
    Node(string const data);
    void Clear();
    const int& Count() const;
    const string _data;
    Node* _pprev;
    Node* _pnext;
    friend class List;           
};


inline Node::Node(string const data): _data(data), _pprev(0), _pnext(0) 
{
}

inline const int& Node::Count()const
{
    if(_pnext == 0)
    {
        return 1;
    }
    return _pnext -> Count() + 1;
}

inline void Node::Clear()
{
    if(_pnext != 0)
    {
        _pnext -> Clear();;
    }    
}
#endif 


list.h

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
#if !defined(LIST_H__)
#define LIST_H__

#include "node.h"

class List
{
public:
    List();
    List(const List& ll);
	List& operator&(const List& ss);
    ~List();
    void PushBack(int data);
    void PushFront(int data);
    void PopBack();
    void PopFront();
    int Front()const;        
    int Back() const;
    bool IsEmpty() const;
    unsigned Count() const;
    void Clear();
    
private:
    Node* _phead;
    Node* _ptail;        
    
};
#endif 


Thank You very much
Last edited on
For your first errors, the values you attempt to return cannot have their address returned. I would recommend creating a static variable to keep track of the count, and simply add one onto the variable each time a Node is created like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Node
{
    Node(string const data);
    void Clear();
    const int& Count() const;
    const string _data;
    Node* _pprev;
    Node* _pnext;
    static int Count; //counts number of nodes
    friend class List;           
};

inline Node::Node(string const data): _data(data), _pprev(0), _pnext(0) 
{
   Count++
}

Then simply change the function to return that value.

Does this help at all?
No, it did not. It caused a bigger load of errors to show up. Anyway, I already solved, thank you for your help. I am posting the code for the answers I needed bellow, for future references.

list.cpp

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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#include "list.h"


List::List(): _phead(0), _ptail(0)
{
}

List::List(const List& list): _phead(0), _ptail(0)
{
    Node* pNode = list._phead;
    while(pNode != 0) 
    {
        PushBack(pNode -> _data);
        pNode = pNode -> _pnext;  
    }   
}

List& List::operator=(const List& list)
{
    if(this != &list)
    {
        Clear();

        Node* pNode = list._phead;
        while(pNode != 0) 
        {
            PushBack(pNode -> _data);
            pNode = pNode -> _pnext;  
        }
    }
    return *this;
}

List::~List()
{
    Clear();
}

bool List::IsEmpty() const
{
    return (_phead == 0);
}    

void List::PushFront(const std::string& data)
{
    Node* pNode = new Node(data);
    
    if(_ptail == 0)
    {
        _phead = pNode;
        _ptail = pNode;
    }
    else
    {
        _phead -> _pprev = pNode;
        pNode -> _pnext = _phead;
        _phead = pNode;        
    }
}

void List::PushBack(const std::string& data)
{
    Node* pNode = new Node(data);
    
    if(_ptail == 0)
    {
        _phead = pNode;
        _ptail = pNode;
    }
    else
    {
        _ptail -> _pnext = pNode;
        pNode -> _pprev = _ptail;
        _ptail = pNode;        
    }
}

void List::PopFront()
{
    if(IsEmpty())
    {
        //TODO: What do we do?
        return;
    }
    if(_phead == _ptail)
    {
        //Only one item in the list
        delete _phead;
        _phead = 0;
        _ptail = 0;
    }
    else
    {
        Node* pNode = _phead;
        _phead = _phead -> _pnext;
        _phead -> _pprev = 0;
        delete pNode;
    }
}

void List::PopBack()
{
    if(IsEmpty())
    {
        //TODO: What do we do?
        return;
    }
    if(_phead == _ptail)
    {
        //Only one item in the list
        delete _phead;
        _phead = 0;
        _ptail = 0;
    }
    else
    {
        Node* pNode = _ptail;
        _ptail = _ptail -> _pprev;
        _ptail -> _pnext = 0;
        delete pNode;
    }
}

const std::string& List::Front() const
{
    if(IsEmpty())
    {
        //TODO: What do we do?
        return 0;
    }
    return _phead -> _data;
    
}

const std::string& List::Back() const
{
    if(IsEmpty())
    {
        //TODO: What do we do?
        return 0;
    }
    return _ptail -> _data;
}

unsigned List::Count() const
{
    if(IsEmpty())
    {
        return 0;
    }    
    //doing it recursively
    return _phead -> Count();
    
    /*
    //doing it iteratively
    int ret = 0;
    Node* pNode = _phead;
    while(pNode != 0)
    {
        pNode = pNode -> _pnext;
        ++ret;
    }
    return ret;
    */
}

void List::Clear()
{
    if(IsEmpty())
    {
        return;
    }    
    
    ///Aaron's method
    while(!IsEmpty())
    {
        PopFront();
    }
    
    
    /*
    //Iterative approach
    Node* pNode = _phead;
    Node* pNext = pNode -> _pnext;
    while(pNext != 0)
    {
        delete pNode;
        pNode = pNext;
        pNext = pNode -> _pnext;
    }
    _ptail = 0;
    _phead = 0;
    */
    
    /*
    //recursive approach
    _phead -> Clear();
    delete _phead;
    _ptail = 0;
    _phead = 0;
    */
    
 }


list_test.cpp

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
#include <iostream>
#include "list.h"

using std::cout;
using std::endl;
    
int main()
{
    
    List ls;

    ls.PushBack("We are glad the Dauphin is so pleasant with us;");
    ls.PushBack("His present and your pains we thank you for:");
    ls.PushBack("When we have march'd our rackets to these balls,");
    ls.PushBack("We will, in France, by God's grace, play a set");
    ls.PushBack("Shall strike his father's crown into the hazard.");
    ls.PushBack("Tell him he hath made a match with such a wrangler");
    ls.PushBack("That all the courts of France will be disturb'd");
    ls.PushBack("With chaces. And we understand him well,");
    ls.PushBack("How he comes o'er us with our wilder days,");
    ls.PushBack("Not measuring what use we made of them.");
    ls.PushBack("We never valued this poor seat of England;");
    ls.PushBack("And therefore, living hence, did give ourself");
    ls.PushBack("To barbarous licence; as 'tis ever common");
    ls.PushBack("That men are merriest when they are from home.");
    ls.PushBack("But tell the Dauphin I will keep my state,");
    ls.PushBack("Be like a king and show my sail of greatness");
    ls.PushBack("When I do rouse me in my throne of France:");
    ls.PushBack("For that I have laid by my majesty");
    ls.PushBack("And plodded like a man for working-days,");
    ls.PushBack("But I will rise there with so full a glory");
    ls.PushBack("That I will dazzle all the eyes of France,");
    ls.PushBack("Yea, strike the Dauphin blind to look on us.");
    ls.PushBack("And tell the pleasant prince this mock of his");
    ls.PushBack("Hath turn'd his balls to gun-stones; and his soul");
    ls.PushBack("Shall stand sore charged for the wasteful vengeance");
    ls.PushBack("That shall fly with them: for many a thousand widows");
    ls.PushBack("Shall this his mock mock out of their dear husbands;");
    ls.PushBack("Mock mothers from their sons, mock castles down;");
    ls.PushBack("And some are yet ungotten and unborn");
    ls.PushBack("That shall have cause to curse the Dauphin's scorn.");
    ls.PushBack("But this lies all within the will of God,");
    ls.PushBack("To whom I do appeal; and in whose name");
    ls.PushBack("Tell you the Dauphin I am coming on,");
    ls.PushBack("To venge me as I may and to put forth");
    ls.PushBack("My rightful hand in a well-hallow'd cause.");
    ls.PushBack("So get you hence in peace; and tell the Dauphin");
    ls.PushBack("His jest will savour but of shallow wit,");
    ls.PushBack("When thousands weep more than did laugh at it.");
    ls.PushBack("Convey them with safe conduct. Fare you well.");

    //Testing the copy ctor
    {
        List lsTemp(ls);

        cout << "Testing copy ctor operations:\n" << endl;     
        while(lsTemp.IsEmpty() == false)
        {
            cout << lsTemp.Front() << "\n";
            lsTemp.PopFront();
        }
    
    }    


    
    
    //Testing the assignment operator
    {
        List lsTemp;
        lsTemp = ls;

        cout << "\n\n\nTesting assignment operator operations:\n " << endl;     
        while(lsTemp.IsEmpty() == false)
        {
            cout << lsTemp.Front() << "\n";
            lsTemp.PopFront();
        }
    }    


    cout << "\n\n\nTesting the original list:\n" << endl ;    
    while(ls.IsEmpty() == false)
    {
        cout << ls.Front() << "\n";
        ls.PopFront();
        
    }    
    
    return 0;
}




list.h

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
#if !defined(LIST_H__)
#define LIST_H__

#include "node.h"

class List
{
public:
    List();
    List(const List& list);
    ~List();
    List& operator=(const List& list);
    void PushBack(const std::string& str);
    void PushFront(const std::string& str);
    void PopBack();
    void PopFront();
    const std::string& Front()const;        
    const std::string& Back() const;
    bool IsEmpty() const;
    unsigned Count() const;
    void Clear();
    
private:
    Node* _phead;
    Node* _ptail;        
    
};
#endif 


node.h

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
#if !defined (NODE_H__)
#define NODE_H__
#include <string>

class Node
{
    Node(const std::string& str);
    void Clear();
    int Count() const;
    std::string _data;
    Node* _pprev;
    Node* _pnext;
    friend class List;           
};


inline Node::Node(const std::string& data): _data(data), _pprev(0), _pnext(0) 
{
}

inline int Node::Count()const
{
    if(_pnext == 0)
    {
        return 1;
    }
    return _pnext -> Count() + 1;
}

inline void Node::Clear()
{
    if(_pnext != 0)
    {
        _pnext -> Clear();;
    }    
}

#endif 
Last edited on
Topic archived. No new replies allowed.