Sign in to follow this  

overloading the operator +

This topic is 4593 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 building a Point3D class and I want to be able to add two points together.
class Point3D
{
private:
    float x, y, z, u, v;
public:
// ...
    Point3D(const float px, const float py, const float pz, const float pu, const float pv); 
    Point3D operator + (const Point3D &that);
};
Is the following construct legal? I'm not sure if I'm allowed to return the local p.
Point3D Point3D::operator + (const Point3D &that)
{
    Point3D p(x+that.x, y+that.y, z+that.z, u+that.u, v+that.v);
    return p;
}

Share this post


Link to post
Share on other sites
It's legal because you're returning by value. That is, in the conceptual theory of how this program executes, the un-named variable that is returned is constructed from Point3D p.

Once your function is exited from, p is destroyed, however, the temporary un-named variable is not until the calling statement has ended. That is:

Point3D a = b + c;

Manually rolled out looks something like this in theory:

Point3D a;
{
Point3D return;
{
Point3D p( b.x + c.x , ... );
return = p;
}
a = return;
}

Of course, assembly code is much lower level, the code is likely optimized down to a.x = b.x + c.x ... or similar, and numerous other changes.

Now, what would have been invalid would have been to return a reference or pointer to p. That is:

const Point3D & Point3D::operator + ( const Point3D & that )
{
Point3D p( ... );
return p;
}

or:

const Point3D * Point3D::operator + ( const Point3D & that )
{
Point3D p( ... );
return &p;
}

As a side note, you should add the const keyword to your function decleration. That is:

Point3D operator + (const Point3D &that);
becomes:
Point3D operator + (const Point3D &that) const;
and:
Point3D Point3D::operator + (const Point3D &that)
becomes:
Point3D Point3D::operator + (const Point3D &that) const

This will allow this code to compile:

const Point3D a;
const Point3D b;

a + b;

Whereas your compiler will cause a compile error saying "you can't do that, trying to call non-const function operator+ on a const object a".

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
It's ok, locals are bad to return when they are pointers or references. You are make a temorary variable on the stack *and* when you return, though. If you just have the line something like "return Point3D(x+that.x, y+that.y, z+that.z, u+that.u, v+that.v);" this gives the compiler a hint/more freedom to optimize.

Share this post


Link to post
Share on other sites
Quote:
Original post by MaulingMonkey
As a side note, you should add the const keyword to your function decleration.

Whereas your compiler will cause a compile error saying "you can't do that, trying to call non-const function operator+ on a const object a".

Hey, thanks a lot!

Share this post


Link to post
Share on other sites
Quote:
Original post by Fred304
Quote:
Original post by MaulingMonkey
As a side note, you should add the const keyword to your function decleration.

Whereas your compiler will cause a compile error saying "you can't do that, trying to call non-const function operator+ on a const object a".

Hey, thanks a lot!


Anytime ^_^. Welcome to the wonderful world of const-correctness ;-).

Share this post


Link to post
Share on other sites
Quote:
Original post by ascorbic
Would this be any faster?

Point3D Point3D::operator + (const Point3D &that) const
{
return Point3D(x+that.x, y+that.y, z+that.z, u+that.u, v+that.v);
}


No (it will compile the same - the compiler will destroy the concept of the "temporary variable" anyway by its register allocation, and in either case should be able to do RVO), but I would write it this way to be more concise :)

Cute parameter name BTW ;)

Anyway. Implementing operator += as well, and then implementing + in terms of += (not the other way around), is a valid optimization:


Point3D& Point3D::operator+= (const Point3D &that) {
x += that.x; y += that.y; z += that.z; u += that.u; v += that.v;
return *this;
}

Point3D Point3D::operator+ (const Point3D &that) const {
Point3D the_other(*this); // copy constructor
the_other += that;
return the_other;
}



This way, there are no copies when you do +=, and one copy when you do +.

The other way, there is still a copy when you do + (because you need to return a new object, and not affect *this or that), and one object construction and one allocation when you do += (one object construction to perform the summation, and then a copy back into *this).

Share this post


Link to post
Share on other sites
Quote:
Original post by ascorbic
Would this be any faster?

Point3D Point3D::operator + (const Point3D &that) const
{
return Point3D(x+that.x, y+that.y, z+that.z, u+that.u, v+that.v);
}
That may depend upon the compiler. It would need to do Named Retrun Value Optimisation, iirc. Regardless, it's still preferable.

Share this post


Link to post
Share on other sites
Quote:
Original post by iMalc
Quote:
Original post by ascorbic
Would this be any faster?

Point3D Point3D::operator + (const Point3D &that) const
{
return Point3D(x+that.x, y+that.y, z+that.z, u+that.u, v+that.v);
}
That may depend upon the compiler. It would need to do Named Retrun Value Optimisation, iirc. Regardless, it's still preferable.

That's actually just RVO, not NRVO. He's using an unnamed temporary as the return value.

I seem to remember a large discussion on the boost mailing list about which compilers actually implement either, and I believe NRVO was implemented more often than RVO.

boost does something like:
#ifdef BOOST_HAS_NRVO
sometype operator+(const sometype &lhs, const sometype &rhs)
{
sometype nrv(lhs);
nrv += rhs
return nrv;
}
#else
sometype operator+(sometype lhs, const sometype &rhs)
{
return lhs += rhs;
}
#endif

Share this post


Link to post
Share on other sites

This topic is 4593 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this