From: Alberto Ganesh Barbati on
Carl Barron ha scritto:
> In article <47ebc3fb$0$14342$e4fe514c(a)news.xs4all.nl>, Niels Dekker -
> no return address <noreply(a)this.is.invalid> wrote:
>
>> const std::string & constFoo = doManipulation("bar");
>>
>> And if the user needs to have non-const access to the returned string, she can
>> still avoid copying, by swapping the result:
>>
>> std::string nonConstFoo;
>> doManipulation("bar").swap(nonConstFoo);
> but std::basic_string<...>::swap(std::basic_string < ...> &) is a
> non const member function and should the swap code should fail to
> compile:)
>

It does compile. It's true that rvalues cannot be bound to non-const
references, but you *can* apply a non-const member function to an
rvalue. This is a well-known asymmetry between

doManipulation("bar").swap(nonConstFoo); // ok

which compiles, as opposed to

std::swap(doManipulation("bar"), nonConstFoo); // illegal in C++03

which doesn't (*).

The use of the swap() member wouldn't compile only if you declared
doManipulation() to return a const std::string but Niels Dekker
specifically suggested to avoid that and I totally agree with him.

HTH,

Ganesh

(*) BTW, C++0x will fix that: we will finally be able to call
std::swap() between an lvalue and an rvalue, provided the type has a
suitable move constructor.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Min-Yu Yang on
"Niels Dekker - no return address" <noreply(a)this.is.invalid> wrote in
message news:47ebc3fb$0$14342$e4fe514c(a)news.xs4all.nl...
> Michael (jeungster) wrote:
>>
>> std::string doManipulation( const std::string & input );
>
> Even if the compiler doesn't do RVO, the caller can still avoid the extra
> copying by binding the result to a const reference:
>
> const std::string & constFoo = doManipulation("bar");

What's the lifetime of the temporary std:string object returned by
doManipulation? Does the standard guarantee that constFoo still references a
valid object after this statement?

Even if the standard guarantees that, the above code is risky because some
unknowing programmer may return that constFoo to a outer scope, which will
have undefined behavior because the temp string for sure will have been
destroyed.

Min-Yu

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Niels Dekker - no return address on
>> std::string nonConstFoo;
>> doManipulation("bar").swap(nonConstFoo);

Carl Barron wrote:
> but std::basic_string<...>::swap(std::basic_string < ...> &) is a
> non const member function and [so] the swap code should fail to
> compile:)

Excuse me, but you're wrong! The OP, Michael, declared doManipulation as
follows:
> std::string doManipulation( const std::string & input );

It's perfectly fine to call a non-const member function of the temporary
object, returned by doManipulation. Because the return type of doManipulation
is itself non-const! In fact this is an exception to the general guideline,
"Use const whenever possible", by Scott Meyers, Effective C++.
www.informit.com/content/images/0201924889/items/item21.html Fortunately Scott
has recently added a note an his errata page,
www.aristeia.com/BookErrata/ec++3e-errata.html:
> [...] cases where non-const by-value returns are good design are not
> difficult to find, e.g., return types of std::vector<T> where callers
> will use swap with an empty vector to "grab" the return value contents
> without copying them.


Kind regards, Niels



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Nevin :-] Liber on
In article
<fcb00168-7ca9-43ac-9d83-ca439e26aa77(a)s8g2000prg.googlegroups.com>,
jeungster(a)gmail.com wrote:

> 1.) I can write the function prototype like this:
>
> void doManipulation( const std::string & input, std::string &
> output ); // (uses side-effect to return ouput string)
>
> 2.) Or, I can write the function prototype like this:
>
> std::string doManipulation( const std::string & input ); // (returns
> the output string directly)

But how do you make the two functions do equivalent things? Their
semantics differ in subtle ways.

In general, to make (1) equivalent to (2), it would have to be written
like (this is pseudocode to show the issues):

void doManipulation(const std::string& input, std::string& output)
{
try
{
// Are input and output the same string object?
if (&input == &output)
// do something magical

if (WAYTOOBIG <= output.capacity())
// time for another trick

// do the work

}
catch (...)
{
// perform more magic
throw;
}
}

Compared with the much simpler but sometimes more expensive:

std::string doManipulation(const std::string& input)
{
// do the work
}

SInce it is easier to take correct code and make it faster when
necessary than to take faster but subtly buggy code and make it correct,
I usually use (2) unless I know (and can back up by measurement) that I
can't afford it.

--
Nevin ":-)" Liber <mailto:nevin(a)eviloverlord.com> 773 961-1620

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Alberto Ganesh Barbati on
Min-Yu Yang ha scritto:
> "Niels Dekker - no return address" <noreply(a)this.is.invalid> wrote in
> message news:47ebc3fb$0$14342$e4fe514c(a)news.xs4all.nl...
>> Michael (jeungster) wrote:
>>>
>>> std::string doManipulation( const std::string & input );
>>
>> Even if the compiler doesn't do RVO, the caller can still avoid the extra
>> copying by binding the result to a const reference:
>>
>> const std::string & constFoo = doManipulation("bar");
>
> What's the lifetime of the temporary std:string object returned by
> doManipulation? Does the standard guarantee that constFoo still
> references a
> valid object after this statement?

Yes, the standard guarantees that the lifetime of the temporary is
extended to match that of the reference (�12.2/5).

> Even if the standard guarantees that, the above code is risky because some
> unknowing programmer may return that constFoo to a outer scope, which will
> have undefined behavior because the temp string for sure will have been
> destroyed.

If the function returns by-reference you have undefined behaviour even
if constFoo is not declared as a reference. It would be bad programming
style in any case.

If the functions returns by-value, the temporary is copied as part of
the return statement before being destroyed, therefore there is no risk
of undefined behaviour, whether constFoo is declared as a reference or not.

HTH,

Ganesh


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]