From: George Neuner on
On Wed, 2 Dec 2009 07:05:08 CST, "Martin B." <0xCDCDCDCD(a)gmx.at>
wrote:

>George Neuner wrote:
>> On Sat, 28 Nov 2009 02:39:57 CST, "Martin B." <0xCDCDCDCD(a)gmx.at>
>> wrote:
>>
>>> George Neuner wrote:
>>>
>>>> My best guess is that it's too much trouble - in general - for the
>>>> compiler to decide whether the temporary return object can be renamed
>>>> and used directly or will need to be destructed in the caller - so
>>>> there is a blanket edict against inlining such functions.
>>> Hmmm ... VC++ will always do RVO, i.e., there will never be a temporary
>>> object for the string object, even if all optimizations are turned off.
>>> So I can't imagine how the temporary could pose a problem here.
>>
>> The compiler always _tries_ to do RVO, but there are plenty of cases
>> where it is not possible - one of which is passing an object by value
>> where a reference is expected (a Microsoft extension).
>>
>> If you do something like:
>>
>> string G() { ... }
>> string F( string &in ) { string out; ...; return out; }
>>
>> string x = F( G() );
>>
>> you'll find that the return value from F() is optimized as expected
>> but for F(G()) the return value from G() is a hidden stack temporary,
>> a reference to which is then passed to F().
>>
>
>Cheers, that's an interesting point.
>One might argue though that the hidden stack temporary "belongs" to the
>F(.) call and thus does say nothing about RVO. :-)
>That is, given:
>
> string G() { string s; ... returns s; }
> string F(string &in) { string out; ... returns out; }
>
>and given two different code versions:
>
> void t3() { // uses MS extension
> string s;
> s = F( G() );
> }
>
> void t4() {
> string s;
> string tmp(G());
> s = F( tmp );
> }
>
>this will essentially generate the same assembly for t3 and t4 so I'm
>really not sure if we can and should say that "RVO does not happen".

I suppose you can make the case that the temporary somehow belongs to
F(), but in any event you can show that it isn't optimized away with
the following:

class myString : public string
{
public:
myString() { cout << '+'; }
myString( char* src ) : string( src ) { cout << '+'; }
myString( myString &src ) : string( src ) { cout << '='; }
~myString() { cout << '-'; }
};

myString GetInput( char* prompt )
{
char input[100];
cout << prompt;
cin.getline( input, 99, '\n');
return myString(input);
}

myString Find(myString &input,myString &oldtext,myString& newtext)
{
size_t where;
where = input.find( oldtext );
if ( where != string::npos )
{
input.replace( where, oldtext.length(), newtext, 0,
newtext.length() );
}
return input;
}

int main( void )
{
myString oldtext = GetInput("Find:");
myString newtext = GetInput("Replace With:");
myString text = Find( GetInput("In:"), oldtext, newtext );
cout << text << endl;
return 0;
}

I'm requiring user input so the compiler doesn't optimize objects away
by value propagation. When you run it, you'll see along with the
prompts and your input "+++=----" ... 3 normal constructions, a copy
construction and 4 destructions - proving that there is a hidden
temporary object.

You do need MS language extensions enabled to compile this.

George

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