-
May 12th, 2008, 03:36 AM
#1
returning objects by reference
hi, I have a class with overloaded operators that return references to new objects instead of the objects themselves. the problem is when I try to chain together a sequence of operations it gives wrong results.
CPoint2d<int> a(100, 100);
CPoint2d<int> b(150, 150);
CPoint2d<int> c(200, 200);
this works:
CPoint2d<int> d = a + b;
this dosn't:
CPoint2d<int> d = a + (b + c);
the only difference I can see is that (b + c) will be evaluated first and return a reference to a's + operator. here's what the function looks like:
template <class T>
CPoint2d<T>& CPoint2d:perator +(const CPoint2d<T> &p) const
{
return CPoint2d<T>(x + p.x, y + p.y);
}
it works if I return by value.
-
May 12th, 2008, 03:47 AM
#2
Re: returning objects by reference
Originally Posted by staticVoid
hi, I have a class with overloaded operators that return references to new objects instead of the objects themselves.
Code:
template <class T>
CPoint2d<T>& CPoint2d::operator +(const CPoint2d<T> &p) const
{
return CPoint2d<T>(x + p.x, y + p.y);
}
You are returning a reference to a local object. When the function returns, that object is gone. So what happens to the reference returned? It's gone too. Therefore that code leads to undefined behaviour.
When you return a reference, you must return a reference to an object that will outlast the lifetime of the function. This means that you can only return references to class members, globals, statics, or dynamically created objects, not locally declared objects.
Regards,
Paul McKenzie
-
May 12th, 2008, 04:08 AM
#3
Re: returning objects by reference
Originally Posted by staticVoid
it works if I return by value.
That's the usual way to write operator +
Operator += returns a reference to the class instance and operator + is often written in terms of operator +=
-
May 12th, 2008, 04:10 AM
#4
Re: returning objects by reference
why then does it work when I initialze a variable with it eg.
CPoint2d<int> d = (a + b)
but not:
CPoint2d<int> d;
d = (a + b);
-
May 12th, 2008, 04:10 AM
#5
Re: returning objects by reference
This is the crib sheet I use to remind myself about operator overloading.
Member functions.
&operator * ()
*operator -> ()
&operator ++ () Return *this
const operator ++ (int) Return original by value
&operator -- () Return *this
const operator -- (int) Return original by value
&operator += (int rhs) Return *this
&operator -= (int rhs) Return *this
Friend functions
bool operator == (const &lhs, const &rhs)
bool operator != (const &lhs, const &rhs)
bool operator < (const &lhs, const &rhs)
operator + (const &lhs, const &rhs) Return by value
operator - (const &lhs, const &rhs) Return by value
Implement + and - operators in terms of += and -=
-
May 12th, 2008, 04:14 AM
#6
Re: returning objects by reference
Originally Posted by staticVoid
why then does it work when I initialze a variable with it eg.
Undefined behaviour + luck.
-
May 12th, 2008, 04:22 AM
#7
Re: returning objects by reference
just shows you - don't always believe what you read - !that when you return a refernce to local object it copy's the object from the stack to the heap and the reference will still be valid.
-
May 12th, 2008, 06:22 AM
#8
Re: returning objects by reference
When you return a reference to something it's often because you don't want to have the overhead of a copy or you want to modify the referred variable.
-
May 12th, 2008, 06:39 AM
#9
Re: returning objects by reference
Originally Posted by staticVoid
just shows you - don't always believe what you read - !that when you return a refernce to local object it copy's the object from the stack to the heap and the reference will still be valid.
What book states that? That makes no sense if the object is gone. When a function returns, local objects are destroyed. So what can a reference be referring to if the local object is gone? References need live objects to be referred to. You can't transfer a reference from one object to another.
Regards,
Paul McKenzie
-
May 12th, 2008, 11:29 AM
#10
Re: returning objects by reference
Originally Posted by Paul McKenzie
What book states that? That makes no sense if the object is gone. When a function returns, local objects are destroyed. So what can a reference be referring to if the local object is gone? References need live objects to be referred to. You can't transfer a reference from one object to another.
Regards,
Paul McKenzie
I can't remember where I read it but it wasn't a book, it was some article on the net. so how to people get around returning by value, instead of using RVO like:
Code:
template <class T>
static void CPoint2d<T>::add(const CPoint2d<T> &a, const CPoint2d<T> &b, CPoint2d<T> &result)
{
result.x = a.x + b.x;
result.y = a.y + b.y;
}
or is this^ the best way to do it? I know in small cases its probaly ok, like CPoint2d<int> to return by value but what if you had say:
Code:
class Big64
{
public:
__int64 rg[10000000];
};
CPoint2d<Big64> a, b, c;
a = b + c;
would that not have a significant reduction in speed?
-
May 12th, 2008, 11:36 AM
#11
Re: returning objects by reference
That is the use of an out parameter, not returning a reference to a local variable. Since the argument passed exists in the caller, it continues to exist when control leaves the function, unlike the local variable that is destroyed.
-
May 12th, 2008, 11:49 AM
#12
Re: returning objects by reference
yes - Return Value Optimization, but what are the benefits of using operator overload if (when returning by value) it is slower than using this method? besides being able to do -> a = b + c / d * e;
-
May 12th, 2008, 11:55 AM
#13
Re: returning objects by reference
Originally Posted by staticVoid
I can't remember where I read it but it wasn't a book, it was some article on the net. so how to people get around returning by value,
In the case of a = b + c, you are returning a new value and assigning it to "a", erasing the old value of whatever "a" had. What if "a" contained members that were dynamically allocated? How would you get around not destroying the old contents and replacing it with the new contents? It must be a live new object that is being assigned, the emphasis on live. A reference is bound to one object, and is bound to it for life. If the life of the object ceases to exist, the reference ceases to exist.
would that not have a significant reduction in speed?
I don't know -- time it and find out if it is significantly slower.
Also, as pointed out, you implement operator + in terms of operator +=. The operator += returns a reference to the existing object. That is where you may be confused.
Code:
SomeObject& operator +=(const SomeObject& rhs)
{
//... whatever you need to do to add
return *this;
}
Then operator + is implemented in terms of +=
Code:
SomeObject operator +(const SomeObject& obj1, const SomeObject& obj2)
{
SomeObject temp = obj1;
return temp += obj2;
}
Regards,
Paul McKenzie
Last edited by Paul McKenzie; May 12th, 2008 at 12:42 PM.
-
May 12th, 2008, 11:56 AM
#14
Re: returning objects by reference
but what are the benefits of using operator overload if (when returning by value) it is slower than using this method? besides being able to do -> a = b + c / d * e;
That's the only benefit: syntactic sugar. You can check out the GMP library; they have managed to avoid this problem of unnecessary temporaries in some cases by the use of expression templates.
-
May 12th, 2008, 11:59 AM
#15
Re: returning objects by reference
Originally Posted by staticVoid
yes - Return Value Optimization, but what are the benefits of using operator overload if (when returning by value) it is slower
How much slower? Is it really slower? What if the reduction in speed (if any) is so insignificant it makes no difference whatsoever?
Regards,
Paul McKenzie
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|