Sign in to follow this  
Structure

In this case is passing by reference faster?

Recommended Posts

Structure    240
Hi, Ive got a fixed point wrapper class that ive been using for a while now. The class is simply Class Fixed { int value; //all overloaded methods etc. } Now my question is, is it quicker to pass this class by reference or by value? If its by reference then the pointer must be dereferenced , but if its by value then a temp object must be constructed. As the data is only 32 bits wide im having trouble working out what is actually faster, any ideas?

Share this post


Link to post
Share on other sites
Structure    240
Ok thanks!

I was kinda leaning towards that as it didn’t seem to make sense to pass over the pointer value then have to dereference it when the data needed could be there already if passed by value.

Share this post


Link to post
Share on other sites
Structure    240
What about in the case of the = operator?

Is this

inline Fixed Fixed::operator=(const Fixed x)
{
return Fixed16(x);
}

Or this faster?

inline Fixed& Fixed::operator=(const Fixed x)
{
m_v = x.m_v;
return *this;
}

Share this post


Link to post
Share on other sites
Quote:

inline Fixed Fixed::operator=(const Fixed x)
{
return Fixed16(x);
}


that will never change the object you're assigning to so if you did:
a = b;//a will still hav its old value!

that's what Im saying is a tad confusing

Share this post


Link to post
Share on other sites
Structure    240
Ahh really…


I think I have a misconception on how that works then.


Why does the operator need to return a value at all then? I thought it was the returned value that was assigned.

Share this post


Link to post
Share on other sites
Quote:
Original post by Structure
Ahh really…


I think I have a misconception on how that works then.


Why does the operator need to return a value at all then? I thought it was the returned value that was assigned.


It doesn't, any assignment work should be done *inside* op=, the reason for returning *this is so that you easily can chain calls i.e. to enable:
a = b = c; to work as expected.

Share this post


Link to post
Share on other sites
JohnBolton    1372
Quote:
Original post by Structure
Or are you talking about something else?


He's saying that the first example is "broken" since it doesn't actually do an assignment. Also, neither checks for self assignment, though I guess it wouldn't matter in this case and the compiler would optimize it away anyway.

As far as speed in this case, both functions (once the first once is fixed) will probably be optimized into exactly the same result.

One more thing. Here is the canonical form of operator=():
    Fixed & Fixed::operator=( Fixed const & x )
{
if ( this != &x )
{
...
}
return *this;
}

Share this post


Link to post
Share on other sites
Structure    240
Right!

I get it now thanks so much for your time and quick replies.


Ive had a lot of fun putting together this class over the last few months its really made me think about how things work at a lower level, very educational. :)

Share this post


Link to post
Share on other sites
Structure    240
hi JohnBolton,


could you explain the danger of not putting the self assignment check in a bit further, as im working on a pda game every cycle counts…

Share this post


Link to post
Share on other sites
Quote:
Original post by Structure
could you explain the danger of not putting the self assignment check in a bit further, as im working on a pda game every cycle counts…


Basicly if you'r class handles dynamic memory or other resources you need to check for self assignment so that you don't free any memory you plan on copying etc.

But for many cases it's actually not a very good way to get that safety a common ideom is to implement assignment as:

T& operator=(const T &other)
{
T temp( other);
this->swap( temp);
return *this;
}


that also yields the benefit of being much easier to make exception safe.
And from an efficency standpoint self assignment checks don't make much sense since you're trading efficency for a very very rare operation at the cost of making every assignment a bit more costly.

So if you can implement assignment safely without self assignment checks do that and if you feel you need for correctness reasons check for self assignment then really use the swap ideom instead.

[Edited by - DigitalDelusion on June 29, 2005 3:27:10 PM]

Share this post


Link to post
Share on other sites
Structure    240
Im trying to understand the benefit of what you’ve done here ,

im assuming the the temp is constructed to give you a copy to work with in the function, but in this case you’ve just not used it, other wise to my very untrained eye ;) it dosnt seem to be doing anything.

Share this post


Link to post
Share on other sites
Whoops! nice catch... should swap with 'temp' obvisouly :p

Sorry 'bout that. Have edited the code to be correct.

The idea is to first copy construct the temporary then swap it with the current object.

That way when you leave op= the temporary holding the old values will go out of scope and take care of cleanup and the original object will start its life as the newly created one.

for those liking succint code that could also be written as

T& operator=(const T &other)
{
T(other).swap( *this);
return *this;
}

Share this post


Link to post
Share on other sites
Structure    240
ahh ok, that got me going for a bit, but actualy prob help me understand it better so thanks! it looks like you can do no wrong...

i think i'll just leave it a basic as posible and go on from there. onwards!....

Share this post


Link to post
Share on other sites
JohnBolton    1372
Quote:
Original post by DigitalDelusion
The idea is to first copy construct the temporary then swap it with the current object.

That way when you leave op= the temporary holding the old values will go out of scope and take care of cleanup and the original object will start its life as the newly created one.


While it may have some advantages, it is going end up being more complicated than necessary. Basically, you are moving the implementation of assignment to a swap function, and you can't simply swap the entire class, you have to swap each member individually.

For example,
    Vector3 & Vector3::operator=( Vector3 const & rhs )
{
if ( this != &rhs )
{
x = rhs.x;
y = rhs.y;
z = rhs.z;
}
return *this;
}
becomes
    Vector3 & Vector3::operator=( Vector3 const & rhs )
{
Vector3 temp( rhs );
swap( temp );
return *this;
}
Vector3 & Vector3::swap( Vector3 & rhs )
{
std::swap( x, rhs.x );
std::swap( y, rhs.y );
std::swap( z, rhs.z );
}
Not only that, but it is generally slower since you also call the copy constructor and do two extra assignments for each member variable. Is it all worth it, just to avoid the if (...)?

Share this post


Link to post
Share on other sites
Quote:
Original post by JohnBoltonIs it all worth it, just to avoid the if (...)?


Do note that your example don't need the if to begin with and is much better of without it for reasons stated in my earlier post.

Since you don't need to check for self assignment if failed the first criterion for using the copy/swap idiom.

Also just checking for self assignment does not help make your code exception safe using copy/swap does.

Share this post


Link to post
Share on other sites

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