From -8002948309717270656
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: f78e5,f5d433881cc29cff,start
X-Google-Attributes: gidf78e5,public
From: bparker@gil.com.au (Brian Parker)
Subject: Named return value optimisation- reprise.
Date: 1997/06/15
Message-ID: <33a345bf.7425526@news.ipswich.gil.com.au>#1/1
X-Deja-AN: 248668406
X-Original-Date: Sun, 15 Jun 1997 03:16:43 GMT
Organization: Global Info-Links News Server
X-Auth: PGPMoose V1.1 PGP comp.std.c++ iQBVAwUBM6RUBEy4NqrwXLNJAQGDtgH/XfGLMowAiL1hGnmcIsHVgUZKJYt2IXM5 t211PdT6s1G+M0LL4LE5a21dwRnVODOxDFG2BgglygDmwxAqJJ7ZHA== =gPhn
Newsgroups: comp.std.c++
Originator: austern@isolde.mti.sgi.com


In a recent thread, the virtues and dangers of the named return value
optimisation were discussed.
I gave a contrived example which would fail if the named return value
optimisation was applied, but the general concensus was that the
example given was badly designed as it confused value and reference
semantics and hence was of no practical significance.

I have since noticed an existing well-known matrix class library which
would fail in a similar (more plausible) example.

The example follows-

In the MV++ matrix library (v 1.5 a) there is a matrix class
MV_Vector_double class which is a vector with value (copy) semantics
e.g.

MV_Vector_double A(10);  // length 10 vector

MV_Vector_double B(A);   // copy of A

MV_Vector_double C;
C = A;			// copy of A

One can, however, initialise it as a view on an existing C array, so
that it can be easily used with C code, thus-

double a[] = {1.0, 2.0, 3.0};

MV_Vector_double D(a, 3, MV_Vector::ref);
D[1] = 4.0;	// set a[1] = 4.0;

Note that this mixing of reference semantics on construction with
value semantics on copying is, I think, a reasonable design choice-
this is similar to the built-in references.

Now we can write a useful function to initialise a vector with a copy
of a C array-

double a[] = {1.0, 2.0, 3.0};

MV_Vector_double Copy_C_array()
{
	MV_Vector_double A(a, 3, MV_Vector::ref);
	return A;
}

MV_Vector_double B = Copy_C_array();
B[1] = 4.0; // a[1] == 2.0 as B is a copy

However, if the NRVO is enabled then B will incorrectly be a reference
to a and hence a[1] == 4.0.

Note that the same problem occurs with the return value optimisation
i.e. if Copy_C_array() was written as-

MV_Vector_double Copy_C_array()
{
	return MV_Vector_double(a, 3, MV_Vector::ref);
}
  
This example is of the same form as my previously posted example, but
it is interesting as it occurs using a well-known matrix package.
Whilst I wouldn't mind such code changes if I had explicitly enabled a
non-standard compiler optimisation, I still find it unsettling that
such non-deterministic behaviour is allowed by the standard.

Although the draft otherwise only guarantees that values are copied
one or more times on pass-by-value or return-by-value, that is a
benign form of non-determinism compared with the semantics-altering
behaviour of zero or more copies that [class.copy] paragraph 15
introduces. 

Any comments on this example?

Brian Parker (bparker@gil.com.au)
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your 
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu 
]



