From 2693443682918086940
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: f78e5,f5d433881cc29cff
X-Google-Attributes: gidf78e5,public
From: bparker@gil.com.au (Brian Parker)
Subject: Re: Named return value optimisation- reprise.
Date: 1997/06/17
Message-ID: <33a5fd76.6138084@news.ipswich.gil.com.au>
X-Deja-AN: 249023037
References: <199706161801.NAA21037@csrlink.net>
X-Original-Date: Tue, 17 Jun 1997 05:28:17 GMT
Organization: Global Info-Links News Server
X-Auth: PGPMoose V1.1 PGP comp.std.c++ iQBFAgUBM6ZUcuEDnX0m9pzZAQFvkwF/X1bWBzQDIK9sdns/sY8kJU6/kaNupTGo eLb/gSbqxoe9RSXNA9vuGnZOjVU1uxnN =ykPv
Newsgroups: comp.std.c++
Originator: fjh@mundook.cs.mu.OZ.AU


On 16 Jun 97 17:46:06 GMT, jpotter@falcon.lhup.edu (John Potter)
wrote:
>...
>We have yet another example which has nothing to do with return value
>optimization.  The temporary which is removed is in main.  It is
>compiler generated and can be removed.  I give two other examples
>which produce the same results "buggy".
>...
>Case 1:
>: 	Vec v = InitVector(c_array);
>Case 2:
>	Vec v2 = c_array;
>Case 3:
>	Vec v3 = Vec(c_array);
>...
>
>Case 3 translation:
>	Vec temp3(c_array);
>	Vec v3(temp3);
>Optimize out temp3 to get
>	Vec v3(c_array);
>
>Case 2 translation:
>	Vec temp2(c_array);
>	Vec v2(c_array);
>Optimize out temp2
>	Vec v2(c_array);
>
>Case 1 translation:
>Functions which return a compound type by value are often implemented
>as a function returning void with a pointer to uninitialized space for
>the return value.
>	Vec temp1space;  // not constructed
>	InitVector(&temp1space, c_array);
>	Vec v(temp1space);
>Optimize out temp1space giving
>	Vec v;  // not constructed
>	InitVector(&v, c_array);
>
>InitVector translation:
>void InitVector(Vec* space, int* p) {
>	Vec temp4(p);
>	copyConstruct(space, temp4);
>	}
>Optimize out temp4
>	construct(space, p);
>
>In all cases, the removed item was an unnamed compiler generated
>temporary.  The removal is allowed by 12.2 and does not require the
>use of 12.8.  The class is broken.  One could also question the
>validity of an operator[] which allows modification of an
>implementation which it does not own.  Not allowing the use of 12.8 in
>the unused version of InitVector would permit the broken class to
>appear to be working properly.  Any code which depends upon copying an
>unnamed temporary is poorly designed. 

Excellent arguments as always; in fact they raise an issue that I
hadn't thought much about.

Your argument is essentially that in the same way that

Vec v3 = Vec(c_array);   	// (1)

can be transformed by the compiler to 

Vec v3(c_array);   	// (2)

then the return value of InitVector can be optimised away.

I would agree with this argument, except that I don't think that even
this optimisation is allowed by 12.2, and so it too relies upon
12.8/15.

12.2/2 is just a non-normative example. The real description of which
temporaries can be elided without 12.8/15 is in 8.5.3 [dcl.init.ref]
which states that when binding an rvalue (temporary) to a const
reference then the compiler can either bind it directly or can make an
arbitrary number of copies before binding the final copy. It is only
these compiler-generated temps that can be "elided" without using
12.8/15, not the initial temporary being copied- I can't find any
allowance by the draft to elide the initial temporary in (1) except
via 12.8/15 (please correct me if I am wrong here).

(1) and (2) are, in fact, definitely not equivalent under 12.2 if e.g.
Vec has an inaccessible copy constructor, as 12.2 states that all
semantic restrictions must be honoured as if the copy was made.

So, if one interprets "object" in 12.8/15 to mean memory used both
directly and indirectly, a compiler *cannot* convert (1) to (2) in
cases such as my example- in any case, it is relying upon 12.8/15.

>  Restricting the use of 12.8 for
>return value optimization would provide a way to code functions which
>allow broken classes to operate, at the expense of preventing
>temporary removal in functions using correct classes.  Use of the
>broken classes can be coded as construction followed by assignment
>without changing the draft.

(actually, the way 12.8/15 is written it can elide *any* copy
including those done via a copy assignment operator, but that is just
an editorial problem)

Let me make it clear that I don't want 12.8/15 restricted *just* to
prevent the return value optimisation. In fact my third preferred
option would be to restrict 12.8/15 to apply *only* to initialisations
and, therefore, the RVO. As I have previously argued, I think that
allowing 12.8/5 to elide copies on pass-by-value is the main flaw and
I think most people have underestimated the danger in destroying the
fundamental axiom that pass-by-value can't alter its argument. The
NRVO and RVO only occur in a much more circumscribed situation- i.e.
initialisations- and so the problems can be worked around provided one
is aware of them (by, as you suggest, using default construction
followed by assignment rather than direct initialisation).

(Incidentally, I would be interested in your opinion of my STL
pass-by-value example in my response to Jason Merrill in this thread.
Do you think 12.8/15 should be allowed to be applied in that case?).

Having said that, I still think that the NRVO and RVO do alter the
semantics of return-by-value and I don't agree with your assessment
that the  MV_Vector_double class or my example class is broken. If one
wants to use a vector class with C arrays then such a design is
required. Some classes do share resources in ways inconsistent with
pure value or reference semantics and in particular when garbage
collection is available as memory is then viewed as owned by the
system and not by any particular object.

My philosophy is that the standard's semantics should be well-defined
and consistent and hence to allow semantics-changing optimisations
only under user control.
 
,Brian Parker (bparker@gil.com.au)
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]



