Re: How safe is returning a value by reference?
On 7/28/2012 2:23 PM, davidkevin@o2.pl wrote:
Hi, I have seen an interesting example of applications of returning a
value by reference from method. But is it really safe? If not could
you give me some clear examples which will show when it is unsafe?
Stroustrup has given in TC++PL among others following sample:
class Matrix { friend Matrix& operator+(const Matrix&, const
Matrix&) };
He have claimed that above code is proper but it causes problems with
memory allocation. I am not sure what he means.
He has stated that: 1. a reference to a result will be passed outside
the function as a reference to a value passed from a function, so
that value can't be an automatic variable. 2. Operator is often used
in an expression more than once so it can't be a local static
variable. 3. Copying a passed value is usually cheaper (with respect
to time of execution, size of code and size of data).
I would like to know what are reasons for which above sentences
holds. Again, I would be grateful for clear examples.
The (1) seems convoluted too much (did you re-type it from any of his
books, by memory?). (1) You cannot return a reference to an automatic
object because by the time you get to use that reference, the object has
been already destroyed. (2) You cannot return a reference to a static
object inside the op+ function because the function could be used more
than once in the same expression, and hence needs to be safely re-entrant.
Next - Stroustrup claim that passing by reference could cause an
improvement of efficiency (however his third from above statements
shows that not necessarily). Ok, but I wonder what happens in code
like that:
Matrix a, b; Matrix c; c=a+b;
If operator+ returns a value by value then that value is returned by
return this ; inside operator+ definition. Then a compiler can
directly assign c to newly created object.
If operator+ has a 'this' to return, it's a non-static member function,
yes? To be that it has to have only one explicit argument, the
right-hand side of the + expression, yes? Then what does it change, the
left-hand side? IOW, in the expression a+b, the matrix 'a' will be
changed? That's absurd.
So, conclusion then is that operator+ cannot 'return this'. It can only
be a friend function or a const member function that *still* returns a
new object, but not 'this'.
If operator+ returns a value by a reference then a copy has to be
created - in other case c would be a same object which a+b is. But
syntax of the assignment denies it - a reference is nothing other
than a synonym for an object so above instruction has to mean that a
value is assigned (and not object).
Can you rephrase that? I have hard time following your thought.
There are certain things you might want to read up on. First, RVO
(return value optimization). The expression c=a+b causes two (usually)
function calls, op+ and op=. If op+ returns a temporary, then the
compiler could optimize away the call to op= to actually use the 'c'
object as the place where the temporary is created for the result of the
addition. So, no copying is involved. Second, perhaps you should get
familiar with C++0x feature called "move assignment", which could help
in this case, giving another way for the compiler to optimize away
copying if it's not necessary since the object *from* which the contents
are copied during the assignment, is temporary and doesn't have to survive.
So as far as I understand when an assignment or an initialization is
executed returning a value by a reference has no impact for capacity.
Am I right?
What's "impact for capacity"? Please define that before I can answer
your "am I right" question.
Later, Stroustrup has given an example of the technique about which
he has said that it causes that a result is not copied:
const int max_matrix_tem = 7;
Matrix& give_matrix_tem() { static int nbuf = 0; static Matrix
buf[max_matrix_tem] nbuf = 0; return buf[nbuf++]; }
Something is not right in that code. A semicolon seems missing somewhere.
Matrix& operator+(const Matrix& arg1, const Matrix& arg2) { Matrix&
res = give_matrix_tem(); //... return tem; }
As far as I understand above code should help to improve efficiency
if we have an expression in which there is more than one operator+.
Yes, a temporary storage is used for the result of op+. That storage is
allocated once and reused, in hopes that none of functions that make use
of that storage are called in some expressions more than 7 times.
But when an assignment to give_matrix_tem should be executed?
Some time inside the op+ after you got the 'res' reference.
> What
should be assigned to give_matrix_tem?
Nothing. You should think of terms of 'res' when implementing the op+
function that uses 'give_matrix_tem'.
> It looks that in the situation
in which buf is full filled a value which give_matrix_tem() will
return next will be old one. And how above code make that a copying
of value is avoided?
Returning a reference to an existing object does not involve copying.
Since 'res' in op+ is a reference to an existing storage object (one of
the elements of the 'buf' array), no copying happens. Or maybe I don't
understand what you're asking...
V
--
I do not respond to top-posted replies, please don't ask