Jump to content
  • Advertisement
Sign in to follow this  
felipedrl

returning a cost reference[SOLVED]

This topic is 4251 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I´m starting to build my engine and I´m beginning with the math core. While I was overaloading the basic operation for my vector class( sum, sub, dot, cross ) a question came to me. should I return a const reference, or just the object. What´s the difference between them? ex:
const Vector3D& operator*( const Vector& v);
Vector3D& operator*( const Vector& v);



I realized that when I return a const reference and I try to do things like n = (( v2 - v1 ) ^ ( v3 - v1 )) I got an error. ( something about discards qualifiers ) Does anyone knows why? Thanks in advance. [Edited by - felipedrl on April 21, 2007 2:30:04 PM]

Share this post


Link to post
Share on other sites
Advertisement
The usual signature for this operator is:

T operator* (const T&) const;


It returns a new value (so no reference), takes a const reference as argument, and is a const method of the class.

Share this post


Link to post
Share on other sites
Expanding on what ToohrVyk said.

The binary operators +, -, *, /, %, >>, << all return a COPY (a new object) and do not modify the arguments in any way.

Just think of a line like: x = a OP b; like x = a + b; to keep you strait. Always ask yourself these questions:

1. Should a be modified by the operation?
2. Should b be modified by the operation?
3. Should x be the same as a or b after the operation?
4. Do I have to make a new object to meet the above requirements?

Depending on the operator, it might or might not.

Many unary operators, such as - (unary), ++, --, [], do not always need to make a copy of their operands. In these cases, you often ask the question about constness instead.

1. If I am returning a reference to myself or something inside of me, that reference should be const IF the method is const (and should NOT be const if the method is NOT const) (return value has same constness as method signature).
2. If I am returning a reference to a parameter or something inside of a parameter, that reference should be be const if the parameter is const (return value has same constness as parameter).
3. If I am returning a new object, or copy of local object, that returned value should normally not be const. (The exception is for systems where you have some always const object type that you register in some central manager ... perhaps your games unit designs are not editable once created ... in that case your method that creates them would return a const reference).

Share this post


Link to post
Share on other sites
First of all, thanks for your great support.
Just to check if I got it right.

1) If I create a new object I should never return a const one.
2) If I do not return a new object, like in some unary operators, I should return const when the method is const or when the receiver is const.


Vector3D operator+( const Vector3D &v) const
{
return Vector3D(x + v.x, y + v.y, z + v.z );
}



Is this the best way to define it?

Thanks for your patience.

Share this post


Link to post
Share on other sites
'x + y' asks "give me the sum of x and y". The resulting sum might not be equal to either x or to y, and clearly neither x nor y should *change* simply because you added them together; therefore, to implement that, we must return a separate thing. Thus, we *create* a value representing the sum, and return it, as a value (you can't properly return a reference to a locally created value, for the same reason you couldn't do it with a pointer.)

'x += y' demands "add y to x". Obviously x should change as a result. We return a reference to (the now-changed) x so that we can do operator chaining (e.g. 'x += y += z').

It is common to implement + in terms of +=, for objects where += is in fact provided. (It is possible to define objects that logically should be "immutable", so that '+=' is deliberately not allowed and '+' has to do the work itself). We simply do this by making a copy of the current object within the function, calling the += on it, and returning the (now-modified) copy:


Vector3D& operator*=(const Vector& v) {
// Implement the operation here, modifying the current object.
return *this; // a reference to self.
}

Vector3D operator*(const Vector& v) const {
Vector3D result(*this); // invoke the copy constructor.
result += v; // modify the copy (not the current object!)...
return result; // ... and return the modified result, which is a new value.
}

Share this post


Link to post
Share on other sites
Since no one has mentioned it yet most binary operators should be free functions taking two arguments, making them member functions prevents the compiler from performing implicit conversions of the left operand, in addition its semantically incorrect to use a member function because you dont want to "tell x to add y to it" you want to "add x and y together" also using non-member functions can aid encapsulation[1][2]

Example:

MyInt i = 0;
// if operator+ is a member
// this will work
i = i + 4;
// but this wont work
i = 4 + i;
// if its a free function both of the above will work

Share this post


Link to post
Share on other sites
Quote:
Original post by felipedrl
Is this the best way to define it?

That code is great, add to it Julian90's recommendation for using a free-floating implementation instead of a member function and it would in fact be the "best way" ... :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!