Pointer, class, overloading

Hi guys,

Have trouble cleaning up code. I can do it without overloading, but code is so much cleaner and elegant when overloaded I would like to become more proficient using this method. Without using ("this" or "->", I have not learned those yet) can someone please show me how to return "solution" so when I send it to the overloaded <<,and the program does not crash? I suspect it has to do with the copy constructor, but I am not sure how to fix it.

Assume both arrays are the same length, this is just a test program to see if I can get overloading working.


Thanks,

Mike

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

// Visual_Test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include <cstdlib>
#include <iomanip>
#include <cmath>
#include <string>
#include <cctype>
#include <vector>
#include <fstream>
using namespace std;
using std::ifstream;
using std::ofstream;
using std::endl;
using std::ios;

const int MAX=10000;

class Test
{
public:
	Test::Test();
	Test::~Test();
	Test::Test(Test& object);

	friend istream& operator>>(istream& input, Test& object);
	friend ostream& operator<<(ostream& output, Test& object);
	friend Test operator+(const Test& obeject1,const Test& object2);

private:
	int *arr;
	int length;
};

int main()
{

	Test one, two, addition;
	cin>>one;
	cout<<one;

	cin>>two;
	cout<<two;

	addition=one+two;//problem here

	cout<<addition;
	_getch();

}
Test::Test()
{

}
Test::Test(Test& object)
{
	arr=new int[object.length];
}
Test::~Test()
{
	delete [] arr;
}
istream& operator>>(istream& input, Test& object)
{
	int next;
	int *dummy=new int[MAX];
	object.arr=dummy;
	object.length=0;
	do
	{
		cout<<"Enter a number: ";
		input>>next;
		object.arr[object.length]=next;
		object.length++;
	}while(next>0);
	object.length--;
	cout<<endl;

	return input;
}
ostream& operator<<(ostream& output, Test& object)
{
	for(int i=0;i<object.length;i++)
		output<<object.arr[i]<<" ";
	cout<<endl;
	return output;
}
Test operator+(const Test& object1,const Test& object2)
{
	Test solution;
	solution.arr=new int[object1.length];
	for(int i=0;i<object1.length;i++)
		solution.arr[i]=object1.arr[i]+object2.arr[i];

	cout<<endl;
	return Test(solution);/////problem here
}
closed account (zb0S216C)
toomanystars wrote:
Test::Test(Test& object);

...is not a copy-constructor. Valid copy-constructors take a constant reference to an instantiation of the class. As a result, when the use of a copy-constructor for your class arises, the compiler will generate its own, which will perform member-wise copying, which can be disastrous if there's DAM (Dynamically Allocated Memory) within the class.

Wazzak
Last edited on
You need to make your copy constructor do a deep copy of the pointer. Otherwise, when the temporary is destructed, it de-allocates the array...the same array that the returned value happens to be pointing to, as it is a copy.
Hi,

I am not sure what a "deep copy" is. Can someone please show me what the constructor needs to look like in order for the program to work? That is without using "this" or "->" which I know nothing about.

Thanks,

Mike
closed account (zb0S216C)
Here's an example of a copy-constructor:

1
2
3
4
5
class Test
{
    Test(const Test &pInstance); // Copy-constructor
    //...
};

A deep-copy is when you give each member its own copy of the data of the instance you passed it. Consider this code:

 
Test A, B(A);

In this code, B's copy-constructor is called with A as its argument. For each member of A, B's members are given an exact copy of A's members. However, this is not the case with DAM. When memory is involved, it's a different story. Consider this:

1
2
3
4
5
6
7
8
9
10
11
12
13
struct Buffer
{
    Buffer() { mMemory = new int(0); }
    Buffer(const Buffer &pInstance) { mMemory = pInstance.mMemory; }
   ~Buffer() { delete mMemory; }

    int *mMemory;
};

int main()
{
    Buffer A, B(A);
}

What happens? when A is constructed, A.mMemory is assigned to DAM. When B is constructed, its copy-constructor is called with A as its argument. This causes B.mMemory to point to the same location as A.mMemory. This is where things start to go wrong. Since A was first on the stack, B's destructor is called first, which deletes the memory B.mMemory points to. Following B's destruction, comes A's destruction. A's destructor is called, which deletes the memory pointed to by A.mMemory. And now: Disaster! The memory was already freed when B's destructor was called.

By creating a deep-copy, B.mMemory would claim its own memory.

Wazzak
Last edited on
The difference between a shallow copy and a deep copy is pretty simple. A shallow copy just does a simple copy of the variables. If you do not supply a copy constructor in a class or struct the compiler will automatically provide a shallow one that will simply copy each variable over.

If you do not have any pointers and/or dynamic data this is fine. If however, you do have pointers and/or dynamic data you need to supply your own copy constructor so that you can make sure that you make a copy of the data that is being pointed to and not just the pointer itself. That way you don't have 2 pointers pointing to the same memory space.

For example, using these variables:

int* num1 = new int;
int* num2;


A shallow copy would do this:

num2 = num1;

This would merely copy the address that num1 is pointing and so they would both be pointing to the same memory location. This is not want you want.

So in this case, since you have pointers and dynamic data you would provide your own copy constructor and inside it you would do this:

num2 = new int;
*num2 = *num1;

This would allocate a new spot on the heap for num2 and then copies the actual data num1 is pointing to into it so now you have 2 different copies that have their own memory.


Here, just compile and run this code to get a better understanding.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int main()
{

	int* num1 = new int;
	int* num2;	
	
	*num1 = 3;

	num2 = num1;

	cout << "They both point to the same 3: " << num1 << " " << *num1 << " " << num2 << " " << *num2 << endl;

	num2 = new int;
	*num2 = *num1;

        cout << "They now point to their own 3's: " << num1 << " " << *num1 << " " << num2 << " " << *num2 << endl;
		

	return 0;
}


Notice that the second time around num2 has a different memory address. That is what you want in a deep copy. That way when you deallocate the pointer, you won't have a dangling pointer because no other pointers will be pointing to it.
Last edited on
I have changed the code to what I understood to be the solution (amongst others), but it still crashes. Do you guys see any problems? Is there perhaps an easier way of returning a pointer class overloaded object?

1
2
3
4
5
6
7
8

Test::Test(const Test& object)
{
	int *t=new int[object.length];

	//for(int i=0;i<object.length;i++)
		*t=*object.arr;
}
In your copy constructor you should not have to declare new data. You only need to copy data that you declared to be part of your class. That is, the data that you already declared in the class declaration.

WHat you are doing in the code above has nothing to do with your copy constructor because you are declaring t to be local to that method so once the method reaches the end t is destroyed. (Or it is supposed to be destroyed. In your case you have a memory leak because you did not de-allocate it's memory before the method ended.)

You need to understand variable scoping first and foremost.

If you declare a variable inside a function or method it only exists in that context. If you declare a variable in your class declaration it will exist as long as a class instance exists.

If you declare a pointer inside a class and use the keyword new to allocate it, you should envision it as being outside of the class itself because when the class instance is destroyed, that pointer is not automatically destroyed. Well, the pointer is, but the data it points to is not. It is up to you to deallocate the data it points to yourself before the class instance is destroyed. The preferable place is the class destructor.

C++ is not a trivial language and you should consider ordering a book on amazon just so you can sit in a chair and read up on it. Trust me, you will learn a lot just by reading. There are too many rules to just tinker and toy with. It's much better to just read it straight from the horses mouth.



Last edited on
1
2
3
4
5
Test::Test(const Test& t) : arr(new int[t.length]), length(t.length)
{
     for (int i=0; i<length; ++i)
          arr[i] = t.arr[i] ;
}


Unfortunately, a working copy constructor isn't going to do the job for you. A copy assignment operator on the other hand..

1
2
3
4
Test& Test::operator=(const Test & t )
{
// ...
}


You're going to need that.
Last edited on
I do have a book, an old "Problem Solving with C++" fifth edition by Walter Savitch. There are no examples provided for overloading & class & pointer & copy constructors so I thought I would give it a shot to see if I can do it. Of course C++ is not a trivial language, but when you are a noob, sometimes you have to resort to tinkering in order to make your program work. Thanks for the help, I will keep trying.

Mike
Mike, I apologize. I forgot that most standard C++ books leave that stuff out.

What you need to do is get a hold of an object oriented C++ book.

But seriously, this thread should supply you with everything you need unless you are trying to copy classes inside of classes that you allocated dynamically. Even then it's the same, you just need to make sure you allocate new storage for them in your copy constructor.


By the way, there are 3 musts when a class or struct contains dynamic data:

~copy constructor
~overloaded assignment operator (=)
~destructor

If you don't provide all 3 you are a shitty programmer. haha
Last edited on
I have read about the "big three" but my book skims over them. Couple that with pointers, and my noobishness, and it becomes a big mess. Do you know of any quality object oriented C++ books with many examples and lot's of problems? If so, please let me know, and I will order it.

Thanks,

Mike
This the book I learned from. It is 10 years old and is not geared towards people just learning C++ but it is straight to the point and you can fully understand inheritance, polymorphism, and the Standard Template Library in about 2 weeks if you are actually interested in it. It's also sold used for around 10 bucks.

http://www.amazon.com/Object-Oriented-Programming-C-2nd-Edition/dp/0130158852/ref=sr_1_4?s=books&ie=UTF8&qid=1334109000&sr=1-4

It's a great book to build a foundation on and then after that you can get some newer books to learn the Windows Foundation Classes or other newer API's if that's your fancy.
Last edited on
Thanks,

I already ordered two books from chapter.ca, so I will put your book on my list, and if I still need more practice after the initial books, I will pick up your recommendation.

Mike
Topic archived. No new replies allowed.