Re: How safe is returning a value by reference?
W dniu sobota, 28 lipca 2012 23:15:15 UTC+2 u=C5=BCytkownik Victor Bazarov =
napisa=C5=82:
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?).
The above text is taken from "The C++ Programming Language", Seventh Editio=
n, chapter 11.6 (Operator overloading: Large objects). I had that book befo=
re my eyes when I was writing my post. But it it is not rewritten a charact=
er to a character - I have a polish edition.
(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.
Understand I things proper that it means that in the situation in which I h=
ave
a variable which was declared in method m() I can not return a reference to=
that object? (It seems to me that more complex situations could lead to su=
ch error but that example has only show about what the problem is).
(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=
..
OK. But how returning the reference to the static object can make that re-e=
ntrant will not be safe?
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'.
Yes, I have made a terrible mistake. I did mean a situation in which a new=
object is returned (which is a sum of a and b).
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.
I want to know if returning a reference make it possible to improve an effi=
ciency of calculations in instructions like:
c=a+b;
In other words: if we have instructions:
c=a+b; //operator+ returns by a value
f=d+e; //operator+ returns by a reference
will one of those more efficient than other? For me it seems that not. In=
fist case return instruction inside operator+ will make that one copy of ob=
ject will be created. When the assignment will be executed a next copy has =
not be created because a+b is temporary so we can use it directly (and I th=
ink that every good compiler will not make that unnecessary copy). In secon=
d case a value is returned by a reference so object is not copied here. But=
copy has to be executed in order to make the assignment possible.
So in both cases one copy is created. So there is no reason for which one v=
ersion should be more efficient than other. Am I right?
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.
Have I used a word "capacity" incorrectly? What I mean was that returning a=
reference has no impact for efficiency.
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=
..
const int max_matrix_tem = 7;
Matrix& give_matrix_tem() {
static int nbuf = 0;
static Matrix buf[max_matrix_tem] nbuf = 0;
if (nbuf==max_matrix_tem) nbuf = 0; //missed line
return buf[nbuf++];
}
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...
That conception (using a buffer of static objects) is still not very clear =
for me. What is a reason for which operator+ know that give_matrix_tem will=
give him an object which it that operator really needs?