Topic: return value optimization and aliasing
Author: "Fernando Cacciola" <fernando_cacciola@hotmail.com>
Date: Mon, 23 Feb 2004 00:32:37 CST Raw View
Hi,
Consider:
struct point
{
point( int x_, int y_ ) : x(x_), y(y_) {}
int x,y ;
}
inline point xform ( point const& p )
{
return point(p.x*p.y,p*x.p.y);
}
int main()
{
point q(10,10);
point& rq = q ;
rq = xform(q);
}
AFAICT, 12.2 allows an implementation to construct the result value of
xform right in the caller's LHS (rp in this case).
Now, being 'rq' an alias for 'q'; and given that the 'p' (the function
argument) is itself another alias for 'p', I think that it is possible for
the call to give the "wrong" result (because p.x or p.y might changed in the
middle)
Is it true that p.x/p.y might be changed in the middle of the result
construction because of the aliasing?
TIA
Fernando Cacciola
SciSoft
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Ben Hutchings <do-not-spam-benh@bwsint.com>
Date: Mon, 23 Feb 2004 11:26:09 CST Raw View
Fernando Cacciola wrote:
> Hi,
>
> Consider:
>
> struct point
> {
> point( int x_, int y_ ) : x(x_), y(y_) {}
> int x,y ;
> }
>
> inline point xform ( point const& p )
> {
> return point(p.x*p.y,p*x.p.y);
> }
> int main()
> {
> point q(10,10);
> point& rq = q ;
> rq = xform(q);
> }
>
> AFAICT, 12.2 allows an implementation to construct the result value of
> xform right in the caller's LHS (rp in this case).
<snip>
No, it doesn't.
Logically what happens is that xform constructs a temporary point(),
copies that to its return value (another temporary), then main()
copies that to a third temporary and assigns that to rq (i.e. q). The
implementation is allowed to avoid the two copies but it cannot
convert an assignment into an initialisation. The assignment to rq
(i.e. q) must be done separately from the construction of the new
point.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kuyper@wizard.net (James Kuyper)
Date: Mon, 23 Feb 2004 11:26:36 CST Raw View
"Fernando Cacciola" <fernando_cacciola@hotmail.com> wrote in message news:<c18u1e$1fb1mp$1@ID-44132.news.uni-berlin.de>...
> Hi,
>
> Consider:
>
> struct point
> {
> point( int x_, int y_ ) : x(x_), y(y_) {}
> int x,y ;
> }
>
> inline point xform ( point const& p )
> {
> return point(p.x*p.y,p*x.p.y);
> }
> int main()
> {
> point q(10,10);
> point& rq = q ;
> rq = xform(q);
> }
>
> AFAICT, 12.2 allows an implementation to construct the result value of
> xform right in the caller's LHS (rp in this case).
> Now, being 'rq' an alias for 'q'; and given that the 'p' (the function
> argument) is itself another alias for 'p', I think that it is possible for
> the call to give the "wrong" result (because p.x or p.y might changed in the
> middle)
>
> Is it true that p.x/p.y might be changed in the middle of the result
> construction because of the aliasing?
No - RVO is subject to the restriction: "Even when the creation of the
temporary object is avoided (12.8), all the semantic restrictions must
be respected as if the temporary object was created." If the temporary
object had been created, the problem that you describe couldn't occur.
Therefore, the implmentation will have to generate code that will
avoid that problem; most likely by creating at least one temporary
that would otherwise have been removeable.
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: "Fernando Cacciola" <fernando_cacciola@hotmail.com>
Date: Mon, 23 Feb 2004 22:48:47 CST Raw View
"James Kuyper" <kuyper@wizard.net> escribi en el mensaje
news:8b42afac.0402230903.2d790dc6@posting.google.com...
> "Fernando Cacciola" <fernando_cacciola@hotmail.com> wrote in message
news:<c18u1e$1fb1mp$1@ID-44132.news.uni-berlin.de>...
> > Hi,
> >
> > Consider:
> >
> > struct point
> > {
> > point( int x_, int y_ ) : x(x_), y(y_) {}
> > int x,y ;
> > }
> >
> > inline point xform ( point const& p )
> > {
> > return point(p.x*p.y,p*x.p.y);
> > }
> > int main()
> > {
> > point q(10,10);
> > point& rq = q ;
> > rq = xform(q);
> > }
> >
> > AFAICT, 12.2 allows an implementation to construct the result value of
> > xform right in the caller's LHS (rp in this case).
> > Now, being 'rq' an alias for 'q'; and given that the 'p' (the function
> > argument) is itself another alias for 'p', I think that it is possible
for
> > the call to give the "wrong" result (because p.x or p.y might changed in
the
> > middle)
> >
> > Is it true that p.x/p.y might be changed in the middle of the result
> > construction because of the aliasing?
>
> No - RVO is subject to the restriction: "Even when the creation of the
> temporary object is avoided (12.8), all the semantic restrictions must
> be respected as if the temporary object was created." If the temporary
> object had been created, the problem that you describe couldn't occur.
> Therefore, the implmentation will have to generate code that will
> avoid that problem; most likely by creating at least one temporary
> that would otherwise have been removeable.
>
OK, I follow your analysis based on the code as I wrote it.
However, 12.2/2 explicitely says than in the case of expressions of the
form: a=f(a) a temporary is required in order to avoid alisaing problems.
My example simply intended to figure out when such aliasing could cause
problems (that's why I used a reference a the caller's LHS),
so, what would be a good example for the problems 12.2/2 is explicitely
trying to avoid.
I figure that depending on the concrete code the compiler might loose track
of aliasing to correctly follow the as if rule (which is what prevents the
problem in this particular example I wrote)
TIA
Fernando Cacciola
SciSoft
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Alberto Barbati <AlbertoBarbati@libero.it>
Date: Tue, 24 Feb 2004 22:33:45 CST Raw View
Fernando Cacciola wrote:
> I figure that depending on the concrete code the compiler might loose track
> of aliasing to correctly follow the as if rule (which is what prevents the
> problem in this particular example I wrote)
Wait a moment. According to my interpretation, all optimization freedom
granted by 12.2 and 12.8 is about avoiding "unnecessary" copy
constructions. However the incriminated line rq = xform(q); is an
assignment and not a copy construction. Under which circumstances an
assignment can be replaced with a copy construction? Only in that case
the compiler could possibly *construct* the result value of xform(q)
directly into rq, therefore incurring in the aliasing problem.
If type point were not a POD, the assignment could not be replaced by
copy construction. However I could not find a statement in the standard
stating that assignment can be replaced by copy construction for PODs.
If all that I've said is correct, yours is a non-problem: the compiler
can't choose to optimize and so aliasing can't occur. Maybe example
12.2/2 could be improved, as the line a = f(a) is a bit misleading (the
problem is not having "a" twice but the presence of the assignment).
Is there something I am missing?
Alberto Barbati
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Ben Hutchings <do-not-spam-benh@bwsint.com>
Date: Wed, 25 Feb 2004 11:46:56 CST Raw View
Fernando Cacciola wrote:
<snip>
> OK, I follow your analysis based on the code as I wrote it.
> However, 12.2/2 explicitely says than in the case of expressions of the
> form: a=f(a) a temporary is required in order to avoid alisaing problems.
> My example simply intended to figure out when such aliasing could cause
> problems (that's why I used a reference a the caller's LHS),
> so, what would be a good example for the problems 12.2/2 is explicitely
> trying to avoid.
<snip>
I think the example is in error - the temporary is required even if
the actual argument to f() is some other variable. I don't see how
the return value of f() can be constructed on top of a, since a has
already been constructed and is now being assigned. Perhaps a defect
report is in order?
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: "Fernando Cacciola" <fernando_cacciola@hotmail.com>
Date: Wed, 25 Feb 2004 21:50:03 CST Raw View
"Ben Hutchings" <do-not-spam-benh@bwsint.com> escribi en el mensaje
news:slrnc3msb0.p3b.do-not-spam-benh@shadbolt.i.decadentplace.org.uk...
> Fernando Cacciola wrote:
> <snip>
> > OK, I follow your analysis based on the code as I wrote it.
> > However, 12.2/2 explicitely says than in the case of expressions of the
> > form: a=f(a) a temporary is required in order to avoid alisaing
problems.
> > My example simply intended to figure out when such aliasing could cause
> > problems (that's why I used a reference a the caller's LHS),
> > so, what would be a good example for the problems 12.2/2 is explicitely
> > trying to avoid.
> <snip>
>
> I think the example is in error - the temporary is required even if
> the actual argument to f() is some other variable. I don't see how
> the return value of f() can be constructed on top of a, since a has
> already been constructed and is now being assigned. Perhaps a defect
> report is in order?
>
I agree with you (and Alberto) that RVO can produce in-place "construction"
(via intialization) but not assignment, so I think the example is misleading
and a DR is in order.
I'll post one later today.
Thanks,
Fenando Cacciola
SciSoft
---
[ 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 ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]