Skip to main content
GameDev.net gamedev.net
🔒 Locked

operator= and copy constructors

Started by GekkoCube Aug 30, 2003 at 5:31 PM 14 replies 1.2k views
Original Post
GekkoCube
GekkoCube
correct me if im wrong, but a copy constructor is needed for the operator= to work? i have a Vector3 class. i have operators * + - / and ^ implemented. i implemented a = operator today. cant figure out if its working because the project compiles, builds, runs, and even accepts code that says Vector3 vect = oldvec (when i comment out the operator= function). this is odd since the Vector3 class shouldnt know what operator= means since its not an operator. here are those functions
      // operator=

      CVector3& operator= ( const CVector3 &v )
      {
         if (this != &v)
         {
            m_X = v.m_X;
            m_Y = v.m_Y;
            m_Z = v.m_Z;
         }
         return *this;
      }

       // Copy constructor.

       CVector3( CVector3<T> &v )
       { 
         m_X = v.m_X;
         m_Y = v.m_Y;
         m_Z = v.m_Z;
       }
dalleboy
dalleboy
If your class looks something like this:

class foo
{
type1 member1;
type2 member2;
type3 member3;
};

The compiler generated cctor and operator= will be something like this:

foo& foo(const foo& rhs)
: member1(rhs.member1)
, member2(rhs.member2)
, member3(rhs.member3)
{
}

foo& operator=(const foo& rhs)
{
member1 = rhs.member1;
member2 = rhs.member2;
member3 = rhs.member3;
return *this;
}


[How To Ask Questions|C++ library of container classes, algorithms and iterators. It provides many of the basic algorithms and data structures of computer science." target="_blank">STL Programmer''s Guide|C++ Style and Technique FAQ - Designer and implementor the C++ programming language." target="_blank">Bjarne FAQ|C++ FAQ Lite - Frequently Asked Questions about the C++ language." target="_blank">C++ FAQ Lite|C++ Reference - The standard C++ library is a collection of functions, constants, classes and objects that extends the C++ language providing basic functionality to interact with the operating system and some standard classes, objects and algorithms that may be commonly needed." target="_blank">C++ Reference|MSDN]
Polymorphic OOP
Polymorphic OOP
quote:
Original post by GekkoCube
correct me if im wrong, but a copy constructor is needed for the operator= to work?

Wrong, they are completely unrelated.

quote:
Original post by GekkoCube
i implemented a = operator today. cant figure out if its working because the project compiles, builds, runs, and even accepts code that says Vector3 vect = oldvec (when i comment out the operator= function).


That's because when you use the = sign in an object construction it does not call operator=, it calls the copy constructor. There the = is just syntactic sugar, not an operator. Doing

Vector3 vect = oldvec;

is just another syntax for

Vector3 vect( oldvec );

With the only difference being that the former is the implicit form and the latter the explicit (the former can only be used if the copy constructor is NOT explicit while the latter can be used anytime a public copy constructor is declared).

If you want to test operator= you'd have to first construct the object and THEN use operator=

for instance:

Vector3 vect;
vect = oldvec;


[edited by - Polymorphic OOP on August 30, 2003 6:47:53 PM]
GekkoCube
GekkoCube
after some testing it appears that my Vector3 class is not copying the vectors i want.

I declared a list of Vector3''s, lets call it:
CVector VectorList[100];

Then I filled this list with vectors using the following:
VectorList[i++] = CVector3(x, y, z);

Now this appears to be a problem because upon reading or just simply displaying everything in this list, i get all 0''s (initialized values).

I keep referring back to the copy constructor and the operator= i posted up because it doesnt seem to be working.

And Polymorphic, I understand what you explained. I am surprised to hear that:
Vector3 vect = oldvec; // requires no copy constructor!
Vector3 vect( oldvec ); // requires one!

I wouldve figured its the other way around.
Polymorphic OOP
Polymorphic OOP
quote:
Original post by GekkoCube
after some testing it appears that my Vector3 class is not copying the vectors i want.

I declared a list of Vector3's, lets call it:
CVector VectorList[100];

Then I filled this list with vectors using the following:
VectorList[i++] = CVector3(x, y, z);

Now this appears to be a problem because upon reading or just simply displaying everything in this list, i get all 0's (initialized values).

I keep referring back to the copy constructor and the operator= i posted up because it doesnt seem to be working.


Post your entire loop and I'll tell you what's wrong. Are you sure the loop is even going through iterations? Are x,y,z initialized to 0?

Also, just a side note, make your copy constructor take a reference to a const CVector3 because you should be able to copy a const vector.

quote:
Original post by GekkoCube
And Polymorphic, I understand what you explained. I am surprised to hear that:
Vector3 vect = oldvec; // requires no copy constructor!
Vector3 vect( oldvec ); // requires one!

I wouldve figured its the other way around.

I'm sorry to say this, but it sounds like you did not understand what I said. Both of those use the copy constructor. The only difference being that the first one can only be performed if you did not declare your copy constructor to be explicit.


[edited by - Polymorphic OOP on August 30, 2003 7:18:03 PM]
original vesoljc
original vesoljc
if (this != &v)

is this really necessary? i''ve heard that things like "a=a" compiler simply ignores... true?
Abnormal behavior of abnormal brain makes me normal...
Polymorphic OOP
Polymorphic OOP
quote:
Original post by original vesoljc
if (this != &v)

is this really necessary?


Not in this particular case because there would be no problems with the implementation, however, in instances where you are dealing with dynamically allocated memory it can be very necissary as you may delete allocated memory and then "copy" a memory address pointing to garbage!

quote:
Original post by original vesoljc
i've heard that things like "a=a" compiler simply ignores... true?


Only if you are working with built-in types such as ints or floats, etc. this does not hold true for objects.

As well, you have to remember that many times the copy may be via pointers, so it would not be clear at compile time. IE You can have two different pointers which happen to be pointing to the same object and then you dereference each and assign one to the other.

[edited by - Polymorphic OOP on August 30, 2003 7:41:01 PM]
GekkoCube
GekkoCube
ok, hold your breath, because im about to post everything related to this....btw, the vectors are initialized to zeros and i know the list is being filled because i print them out before i try to copy them.

here''s all the code.

// class CVector3

// A 3d vector class of all inlined functions.

template< class T >
class CVector3 {
public:
// Constructor.

CVector3( T x=0, T y=0, T z=0 ) : m_X(x), m_Y(y), m_Z(z)
{

}

// Copy constructor.

CVector3( const CVector3<T> &v )
{
m_X = v.m_X;
m_Y = v.m_Y;
m_Z = v.m_Z;
}

// Destructor.

~CVector3()
{

}

// Assignment operator

CVector3& operator= ( const CVector3 &v )
{
if (this != &v)
{
m_X = v.m_X;
m_Y = v.m_Y;
m_Z = v.m_Z;
}
return *this;
}

// Addition, operator overloaded.

CVector3 operator+ ( const CVector3 v ) const
{
return CVector3( (m_X + v.m_x),
(m_Y + v.m_Y),
(m_Z + v.m_Z) );
}

// Subtraction, operator overloaded.

CVector3 operator- ( const CVector3 v ) const
{
return CVector3( (m_X - v.m_x),
(m_Y - v.m_Y),
(m_Z - v.m_Z) );
}

// Dot-product of 2 vectors, must return a scalar float.

CVector3 operator* ( const CVector3 v )
{
return CVector3( (m_X * v.m_x),
(m_Y * v.m_Y),
(m_Z * v.m_Z) );
}

// Cross-product of 2 vectors, must return a D3DXVECTOR3.

CVector3 operator^ ( const CVector3 v ) const
{
return CVector3( ((m_Y * v.m_Z) - (m_Z * v.m_Y)),
((m_Z * v.m_X) - (m_X * v.m_Z)),
((m_X * v.m_Y) - (m)Y * v.m_X)) );
}

// Divide two vectors //

/*CVector3 operator/ ( const CVector3 v )
{
// no implementation...
}*/


// Get the length of the vector

float Length()
{
return (float)sqrt( (v.x * v.x) + (v.y * v.y) + (v.z * v.z) );
}

// Get ArcCosine, returns a scalar float.

float ArcCosine( const CVector3 v ) const
{
// Formula: ArcCosine( (dot product) / (length v1 * length v2) ).

return (float)acos( (this * v) / (Length() * v.Length()) );
}

public:
T m_X;
T m_Y;
T m_Z;
};


pCode SNIPPET where cvector3 is being used...(simplified the code for readability, here is the jist of it).

if ((file = fopen(pfilename, "r")))
{
// get header info.

fgets(line, 50, file);
// do some string tokenizing here to get values

// for x, y, and z.


m_NodeList = new CVector3<float>[m_NodeLength];

CVector3<float> v(x, y, z);
m_NodeList[ni++] = v;

}
Polymorphic OOP
Polymorphic OOP
quote:
Original post by GekkoCube
pCode SNIPPET where cvector3 is being used...(simplified the code for readability, here is the jist of it).


I can't say I'm seeing any loop for copying, all I see is a single assignment. Also -- why don't you just read the values directly into the nodelist? I don't see a reason why you need two copies.

I noticed that you wrote out a declaration for division of a vector by a vector. This operation is not mathematically defined, and, just the same, you should not attempt to implement one as it would not make mathematical or logical sense. As well,, your other operations are taking objects, when it should be more efficient to instead have them take references to const objects. Also, you can get rid of the destructor as the defaul destructor will suffice.

I also wouldn't recommend overloading ^ for cross product as it doesn't really match up with the rules of operation of the cross product of vectors. If you keep it as an overloaded ^, then just remember to always use parenthesis to ensure it's doing exactly what you want.

You are forgetting to derefence "this" in your ArcCosine function. Either use *this, or explicitly call operator* by doing

return (float)acos( (operator*(v)) / (Length() * v.Length()) );

Finally, look over your use of const and try to use it much more than you already are. For instance, all of your operators (except for operator=) as well as your length function can and should be const (check your operator*).

[edited by - Polymorphic OOP on August 30, 2003 11:34:37 PM]
MauMan
MauMan
I tried this with your code and it seemed to work fine:


#include <iostream>

int main()
{
CVector3<float>* a = new CVector3<float>[100];

for ( int i = 0; i < 100; i++ )
{
a[i] = CVector3<float>( i, i, i );
}

for ( int i = 0; i < 100; i++ )
{
std::cout << a[i].m_X << ", " << a[i].m_Y << ", " << a[i].m_Z << "\n" ;
}

return 0;
}
---CyberbrineDreamsSuspected implementation of the Windows idle loop: void idle_loop() { *((char*)rand()) = 0; }
GekkoCube
GekkoCube
thanks for all the extra stuff, i appreciate that.
Maumau, the problem comes when i try to assign a vector to another. printing the results does not yield results it should be.

i''ll completely redo my vector class too!
original vesoljc
original vesoljc
one more thingy...
when checking for self assignement, is it better to use

(this != &lRhs)

or

(*this != lRhs)
Abnormal behavior of abnormal brain makes me normal...
Lektrix
Lektrix
The expression:

this != &rhs

will check that you are not assigning one object to the exact same object, i.e. that this and &rhs don't point to the same object in memory. On the other hand, the expression:

*this != rhs

will call the overloaded operator!=() for the/based on the types, if indeed one is defined (i.e. appropriate semantics). This will be a comparison of the data that the objects represent (or however it is implemented), and not a comparison of whether the addresses point to the same object.

[ Google || Start Here || ACCU || STL || Boost || MSDN || GotW || MSVC++ Library Fixes || BarrysWorld || E-Mail Me ]

[edited by - Lektrix on September 2, 2003 12:42:27 PM]
Malone1234
Malone1234
One more thing, your dot product function returns a CVector3 object. But the result of a dot product is a scalar, not a vector. I think you''re code should be more like this...


// Dot-product of 2 vectors, must return a scalar float.

// I also changed it to pass v by reference, much more efficient.

double operator* ( const CVector3& v )
{
return (m_X * v.m_x) + (m_Y * v.m_Y) + (m_Z * v.m_Z);
}

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.