confusion with copy constructor and operator overloading

K

Kelly Mandrake

I've implemented a class with operator+ overloaded and I also provided
my own copy constructor; The problem is my copy constructor is being
called twise and I dont understand why. I believe the copy constructor
is being called when I add the two class objects. But if this is so,
then why because I have overloaded the + operator should I not get the
result from that and not from copy constructor?

I have the following:

int main(int argc, char *argv[])
{
CVector a(2,5);
CVector b(3,6);
CVector c;

c = a + b;

cout << "X: " << c.GetX() << " Y: " << c.GetY() << endl;

DisplayCopy(c);

system("PAUSE");
return EXIT_SUCCESS;
}

CVector CVector::eek:perator+(CVector param)
{
CVector temp;

temp.SetX( x + param.GetX() );
temp.SetY( y + param.GetY() );

return temp;
}

CVector::CVector(const CVector &rhs)
{
cout << "Inside Copy Constructor..." << endl;
x = rhs.x + 3;
y = rhs.y + 3;
}

void DisplayCopy(CVector copy)
{
cout << "X: " << copy.GetX() << " Y: " << copy.GetY() << endl;
}

==================================================

class CVector
{
public:
CVector(int valueX = 0, int valueY = 0): x(valueX), y(valueY) {}
CVector(const CVector &rhs); // Copy Constructor
CVector operator+(CVector param);

int GetX() const { return x; }
int GetY() const { return y; }
void SetX(int valueX) { x = valueX; }
void SetY(int valueY) { y = valueY; }
protected:
int x, y;
};

void DisplayCopy(CVector copy);
 
E

E. Robert Tisdale

Kelly said:
I've implemented a class with operator+ overloaded
and I also provided my own copy constructor; The problem is [that]
my copy constructor is being called twice and I don't understand why.

You pass the operands by value instead of const reference.
I believe the copy constructor is being called
when I add the two class objects.
But if this is so, then why because I have overloaded the + operator
should I not get the result from that and not from copy constructor?
cat main.cc
#include <iostream>

class CVector {
public:
CVector(int valueX = 0, int valueY = 0):
x(valueX), y(valueY) { }
CVector(const CVector &rhs); // Copy Constructor
CVector operator+(const CVector& param) const;

int GetX() const { return x; }
int GetY() const { return y; }
void SetX(int valueX) { x = valueX; }
void SetY(int valueY) { y = valueY; }
protected:
int x, y;
};

inline
CVector CVector::eek:perator+(const CVector& param) const {
return CVector(x + param.GetX(), y + param.GetY());
}

inline
CVector::CVector(const CVector &rhs) {
std::cout << "Inside Copy Constructor..." << std::endl;
x = rhs.x + 3;
y = rhs.y + 3;
}

inline
void DisplayCopy(const CVector& copy) {
std::cout << "X: " << copy.GetX()
<< " Y: " << copy.GetY() << std::endl;
}

int main(int argc, char *argv[]) {
CVector a(2, 5);
CVector b(3, 6);
CVector c = a + b;

std::cout << "X: " << c.GetX()
<< " Y: " << c.GetY() << std::endl;

DisplayCopy(c);

system("PAUSE");
return EXIT_SUCCESS;
}
g++ -Wall -ansi -pedantic -o main main.cc
./main
X: 5 Y: 11
X: 5 Y: 11
sh: line 1: PAUSE: command not found
 
L

Larry Brasfield

Kelly Mandrake said:
I've implemented a class with operator+ overloaded and I also provided
my own copy constructor; The problem is my copy constructor is being
called twise and I dont understand why. I believe the copy constructor
is being called when I add the two class objects. But if this is so,
then why because I have overloaded the + operator should I not get the
result from that and not from copy constructor?

I have the following:

int main(int argc, char *argv[])
{
CVector a(2,5);
CVector b(3,6);
CVector c;

c = a + b;

cout << "X: " << c.GetX() << " Y: " << c.GetY() << endl;

DisplayCopy(c);

system("PAUSE");
return EXIT_SUCCESS;
}

CVector CVector::eek:perator+(CVector param)
{
CVector temp;

temp.SetX( x + param.GetX() );
temp.SetY( y + param.GetY() );

return temp;
}

CVector::CVector(const CVector &rhs)
{
cout << "Inside Copy Constructor..." << endl;
x = rhs.x + 3;
y = rhs.y + 3;
}

void DisplayCopy(CVector copy)
{
cout << "X: " << copy.GetX() << " Y: " << copy.GetY() << endl;
}

==================================================

class CVector
{
public:
CVector(int valueX = 0, int valueY = 0): x(valueX), y(valueY) {}
CVector(const CVector &rhs); // Copy Constructor
CVector operator+(CVector param);

You should pass the param by const reference.
For example:
CVector operator+(const CVector & param);
This will eliminate a copy as the parameter is passed.
int GetX() const { return x; }
int GetY() const { return y; }
void SetX(int valueX) { x = valueX; }
void SetY(int valueY) { y = valueY; }
protected:
int x, y;
};

void DisplayCopy(CVector copy);

That parameter could also be passed by const reference.
 
K

Kelly Mandrake

I changed it now so that it takes a const reference and of cource it
works fine now. I can see it now that it calls copy constructor
because im passing by value but when I read my code over and over I
wasnt seeing this. Thanks for all the help everyone.
 
K

Kelly Mandrake

In reguards to Roberts post can I ask why it is you recoment moveing my
inline methods out of the class. Is this to do with a standard, please
explain because If it is a standard I will try to follow it from now
on.
 
E

E. Robert Tisdale

Kelly said:
In regards to Robert's post,
Can I ask why it is [that] you recommend
moving my inline methods out of the class.
Is this to do with a standard,
please explain because, if it is a standard,
I will try to follow it from now on.

I did *not* move any [inline] methods
out of your CVector class definition.
You *declared* CVector::eek:perator+(CVector)
and CVector::CVector(const CVector&)
in your CVector class definition
then *defined* them outside of the CVector class definition.
These are lightweight functions which should be inline'd
but they *must* be defined as inline functions
*before* they are invoked (in function main(int, char**) in this case).

"Standard" practice is to place the class definition
along with any inline function definition in a header file:
cat CVector.h
#ifndef GUARD_CVECTOR_H
#define GUARD_CVECTOR_H 1

#include <iostream>

class CVector {
public:
CVector(int valueX = 0, int valueY = 0):
x(valueX), y(valueY) { }
CVector(const CVector &rhs); // Copy Constructor
CVector operator+(const CVector& param) const;

int GetX() const { return x; }
int GetY() const { return y; }
void SetX(int valueX) { x = valueX; }
void SetY(int valueY) { y = valueY; }
protected:
int x, y;
};

inline
CVector CVector::eek:perator+(const CVector& param) const {
return CVector(x + param.GetX(), y + param.GetY());
}

inline
CVector::CVector(const CVector &rhs) {
std::cout << "Inside Copy Constructor..." << std::endl;
x = rhs.x + 3;
y = rhs.y + 3;
}

#endif//GUARD_CVECTOR_H

then include it in each source file that references CVector:
cat main.cc
#include "CVector.h"

inline
void DisplayCopy(const CVector& copy) {
std::cout << "X: " << copy.GetX()
<< " Y: " << copy.GetY() << std::endl;
}

int main(int argc, char *argv[]) {
CVector a(2, 5);
CVector b(3, 6);
CVector c = a + b;

std::cout << "X: " << c.GetX()
<< " Y: " << c.GetY() << std::endl;

DisplayCopy(c);

system("PAUSE");
return EXIT_SUCCESS;
}
g++ -Wall -ansi -pedantic -o main main.cc
./main
X: 5 Y: 11
X: 5 Y: 11
sh: line 1: PAUSE: command not found
 
K

Kelly Mandrake

Ok I see now what you mean that you simply added the keywords inline.
Ive been putting the definitions inside my class alot too. So these
are considered light weight because they only have a few lines, or is
there a rule of thumb to determine weather to make them inline or not.
 
E

E. Robert Tisdale

Kelly said:
Ok I see now what you mean that you simply added the keywords inline.
I've been putting the definitions inside my class alot too.

So do I if the class definition is short (less than a page).
But, if the class definition becomes very long,
I move constructor, operator and member and frient function definitions
(usually all of them) out of the class definition.
This also allows me to reorder these definitions
so that inline member functions are defined
before other member functions that use them.
So these are considered light weight
because they only have a few lines. Or is there a rule of thumb
to determine weather to make them inline or not.

Actually, I don't worry about this.
inline function slow down compilation
and, consequently, the code-compile-test-debug development cycle
so I arrange my code so that I can build with either inline or external
function definitions:
cat file.h
#ifndef GUARD_FILE_H
#define GUARD_FILE_H 1

#ifdef EFINE_INLINE
inline
double dot(const double x[], const double y[], int n) {
double t = 0.0;
for (int j = 0; j < n; ++j)
t += x[j]*y[j];
return t;
}
#else //EFINE_INLINE
double dot(const double x[], const double y[], int n);
#endif//EFINE_INLINE

#endif//GUARD_FILE_H
cat file.cc
#undef EFINE_INLINE
#include "file.h"

double dot(const double x[], const double y[], int n) {
double t = 0.0;
for (int j = 0; j < n; ++j)
t += x[j]*y[j];
return t;
}
cat main.cc
#include "file.h"

int main (int argc, char* argv[]) {
// code to invoke dot
return 0;
}
g++ -Wall -ansi -pedantic -c file.cc

Now, for all of your development, testing and debugging, you invoke
g++ -Wall -ansi -pedantic -o main main.cc file.o

This compiles and links quickly but may run slowly.

Then, just before you are ready to release and distribute your code,
you invoke
g++ -Wall -ansi -pedantic -DEFINE_INLINE -O2 -o main main.cc

This may take much longer to compile
but the optimized inline'd code may run much faster.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top