If this is a temporary, IIRC, it is guaranteed to exist during
the evaluation of the full-expression of the call site? So one
either has to pass it to another function there or copy it to
an object with longer life time.

The tutorial also uses:

string my_string3 = my_string1 + my_string2;

This seems to be »copy initialization«.

Is it of any advantage to use »direct initialization« in this
case? Which would be:

string my_string3( my_string1 + my_string2 );

Are the any guidelines, when to prefer copy initialization
and when to prefer direct initialization?

Ok, and I assume, what one can never to with a temporary
object, is to bind a reference name to it, as in:

string & my_string3( my_string1 + my_string2 );

But, this would be allowed with a const reference, because
for this special case ISO C++ extends the lifetime?

string const & my_string3( my_string1 + my_string2 );

Is this what »GotW #88« is about?

So for the same reason, a function with a reference parameter
can not be called with a temporary, unless the reference
parameter is const?

Actually if you count temporaries separate from 'scope-based', then
there is the fourth - static.
> When »a« and »b« are instances of »::std::string«, what is the
> lifetime of »a+b«?

It's a temporary.
>
> A tutorial page, chosen at random,
>
> http://www.cprogramming.com/tutorial/string.html
>
> does not seem to mention or answer this question. Shouldn't
> this be very important for every programmer to know from the
> moment he starts to use objects?
>
> When a function returns a instance of a class, is it the most
> common case that it returns a temporary, so that this can be
> assumed, unless the documentation tells something else?
>
> Is it ok to return a temporary, as in the following example?
>
> ::std::string f()
> { ::std::string const a( "alpha" );
> ::std::string const b( "beta" );
> return a + b; }

Yes, it is.
> If this is a temporary, IIRC, it is guaranteed to exist during
> the evaluation of the full-expression of the call site? So one
> either has to pass it to another function there or copy it to
> an object with longer life time.

It is.
> Is it of any advantage to use »direct initialization« in this
> case? Which would be:
>
> string my_string3( my_string1 + my_string2 );

No, in this case they are equivalent.
> Are the any guidelines, when to prefer copy initialization
> and when to prefer direct initialization?

Always prefer direct initialisation.
>
> Ok, and I assume, what one can never to with a temporary
> object, is to bind a reference name to it, as in:
>
> string & my_string3( my_string1 + my_string2 );
>
> But, this would be allowed with a const reference, because
> for this special case ISO C++ extends the lifetime?
>
> string const & my_string3( my_string1 + my_string2 );

Correct.
> Is this what »GotW #88« is about?

Probably. I didn't look.
> So for the same reason, a function with a reference parameter
> can not be called with a temporary, unless the reference
> parameter is const?

Yes.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

It's OK to use a ref to const if you don't care about re-using the
object or changing it. Keep in mind though, that it still makes the
code somewhat convoluted, and that is justified by what seems to be
premature optimisation. It's easier on a human brain to deal with 'c'
since it's an object (and there is an object behind 'd' as well), and
the copying of this kind is usually taken care of by the optimizing
compiler.

Optimize what you've measured.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

There are more than that. There's static lifetime, of
course, and there's the lifetime of objects thrown as
exceptions, and there may be a few others that I've
forgotten. (IIRC, function arguments also have a special
lifetime.)
> When »a« and »b« are instances of »::std::string«, what is the
> lifetime of »a+b«?

It's a temporary, so the lifetime is until the end of the
full expression. With a couple of obvious exceptions, and
one not so obvious one, but at least until the end of the
full expression.
> A tutorial page, chosen at random,

Don't choose your tutorials at random. There's a lot of
junk out there. (No comment on the link you give---I've not
seen it. But if you reall choose at random, you're more
likely to get junk than anything worthwhile.)
> http://www.cprogramming.com/tutorial/string.html
> does not seem to mention or answer this question. Shouldn't
> this be very important for every programmer to know from the
> moment he starts to use objects?

It depends on the object. For objects like std::string, all
you really need to know is the minimum lifetime, and most of
the time, not even that.
> When a function returns a instance of a class, is it the
> most common case that it returns a temporary, so that
> this can be assumed, unless the documentation tells
> something else?

By definition, the return value of a function is a
temporary.
> Is it ok to return a temporary, as in the following example?
> ::std::string f()
> { ::std::string const a( "alpha" );
> ::std::string const b( "beta" );
> return a + b; }

Yes.
> If this is a temporary, IIRC, it is guaranteed to exist
> during the evaluation of the full-expression of the call
> site? So one either has to pass it to another function
> there or copy it to an object with longer life time.

There's (officially) a copy. Officially, because the
standard explicitly gives the compiler the right to
eliminate it, by merging the temporary a+b with the
temporary returned from the function. Most compilers
actually do this optimization.
> The tutorial also uses:
> string my_string3 = my_string1 + my_string2;
> This seems to be »copy initialization«.

Formally.
> Is it of any advantage to use »direct initialization« in this
> case? Which would be:
> string my_string3( my_string1 + my_string2 );

Since the type of string1+string2 is the same as the target
type, the two are effectively the same.
> Are the any guidelines, when to prefer copy
> initialization and when to prefer direct initialization?

Do what the house coding guidelines say.
> Ok, and I assume, what one can never to with a temporary
> object, is to bind a reference name to it, as in:
> string & my_string3( my_string1 + my_string2 );
> But, this would be allowed with a const reference,
> because for this special case ISO C++ extends the
> lifetime?

Exact. But the effect is not transitive; the lifetime is
only extended to match the reference initialized with the
temporary, not to other references which were initialized
from that reference.
> string const & my_string3( my_string1 + my_string2 );
> Is this what »GotW #88« is about?

Yes.
> So for the same reason, a function with a reference
> parameter can not be called with a temporary, unless the
> reference parameter is const?

Yes, but that has nothing to do with lifetime. It's just a
rule. The original rule allowed binding a temporary to any
reference. People got into trouble with temporaries that
were the result of implicit conversions, e.g.:

The rule is simple: alway prefer copy initialization, to
avoid the most embarrassing parse you refer to, and always
prefer direct initialization, so that novice readers won't
confuse it with assignment.

You're damned if you do, and damned if you don't.

(Also, I can remember one very old compiler which didn't
accept direct initialization for basic types, pointers and
references.)

No. Line 3 should be avoided, because it isn't idiomatic,
and because it depends on a less known and less obvious
feature. In general, std::string is designed to have value
semantics, so you use it like a value, i.e. like an int.
And don't worry about the rest. (The only time the rest
would be relevant is when you have to expose the internals,
e.g. using c_str() because you have to pass the pointer to a
legacy function.)

James Kanze <> writes:
>feature. In general, std::string is designed to have value
>semantics, so you use it like a value, i.e. like an int.
>And don't worry about the rest. (The only time the rest
>would be relevant is when you have to expose the internals,
>e.g. using c_str() because you have to pass the pointer to a
>legacy function.)

Thanks!

So, unless »c_str()« (or »new« or »delete«) is used, there is
no means to obtain a reference to a ::std::string object, that
already has ceased to exist?

Could a malicious programmer somehow construct code that is
accepted by the compiler, does not use »new« or »delete«, and
still has either a memory leak or a use of or a reference to
an object that already has ceased to exist?

~~

Maybe using the property that the lifetime extension for
temporaries is not transitive?

::std::string const & c( a + b );

What do I have to do now with »c« to intentionally create a
bug where this lack of transitivity matters?

Stefan Ram schrieb:
> Could a malicious programmer somehow construct code that is
> accepted by the compiler, does not use »new« or »delete«, and
> still has either a memory leak or a use of or a reference to
> an object that already has ceased to exist?

int& badFunction()
{
int i;
return i;
}

This sometimes happens with local arrays used for c-style strings.
The variable is gone, but the function returns a reference or pointer
referring to it.
> ~~
>
> Maybe using the property that the lifetime extension for
> temporaries is not transitive?
>
> ::std::string const & c( a + b );
>
> What do I have to do now with »c« to intentionally create a
> bug where this lack of transitivity matters?
>

James Kanze <> writes:
>Exact. But the effect is not transitive; the lifetime is
>only extended to match the reference initialized with the
>temporary, not to other references which were initialized
>from that reference.
>>string const & my_string3( my_string1 + my_string2 );

I am trying to construct an example where this intransitivity
can be seen. First attempt:

Line 0 and line 1 bind »a« and »b« to temporaries.
In line 2, »a + b« creates another temporary object, called »c«.
In line 3, the intransitivity seems to apply, but since the scope
of »d« is a part of the scope of »c«, the object »d« will live as
long as »c« lives, so »d« will also live until control exits
the block. So far, there should be no »dangling references«.

For the same reason, it should be okay to call a function
»void f( ::std::string const & x );« with »c«: Because the
lifetime of the incarnation of this function is a part of the
lifetime of the block containing the reference »c«.

One might try to create a dangling reference by »return d;«
in »::std::string const & f(){ /* code from above */ return d; }«.
This will indeed succeed (to create a dangling reference).
So is this the situation, where the intransitivity can be observed?

But the following also seems to return a dangling reference,
while the result is the first const reference the temporary is
bound to.

On Apr 11, 5:19 pm, -berlin.de (Stefan Ram) wrote:
> James Kanze <> writes:
> >Exact. But the effect is not transitive; the lifetime is
> >only extended to match the reference initialized with the
> >temporary, not to other references which were initialized
> >from that reference.
> >>string const & my_string3( my_string1 + my_string2 );
> I am trying to construct an example where this
> intransitivity can be seen.

Two cases, really. (Maybe more, but two occur off hand.) As
above, using the temporary to initialize a reference to a
function which returns it, and using the reference in the
initialization of a dynamically allocated object.
> But the following also seems to return a dangling reference,
> while the result is the first const reference the temporary
> is bound to.
> ::std::string const & f(){ return "a"; }

Yes. But this is more or less the classical "don't return a
reference or a pointer to a local variable or temporary. There
are two absolute limits to the lifetime of a temporary: the full
expression it is created in is the lower limit (unless one
considers function parameters temporaries), and the scope in
which the temporary is created is the upper one---all rules
extending the lifetime take second rang to this one.

A good example of this second rule coming into play:

class C { C() ; std::string const& rs ; } ;

C::C()
: rs( "abc" )
{
}

Clearly, rs is initialized with a temporary. Directly, so the
lifetime should be extended. Which it is, but only until the
end of the constructor. (The reason for this is simple: where
does the compiler put the temporary if its lifetime is to
outlive the call to the constructor?)

Finally: I would like to one again stress that std::string is a
value type. You should use it exactly like you would int or
double, at least with regards to whether to use a reference or
not. You don't generally have local variables or members which
are references to int or double, and you shouldn't generally
have local variables or members which are references to string.
(There are exceptions, of course, but these generally involve
references to objects which outlive the function.)

Share This Page

Welcome to The Coding Forums!

Welcome to the Coding Forums, the place to chat about anything related to programming and coding languages.

Please join our friendly community by clicking the button below - it only takes a few seconds and is totally free. You'll be able to ask questions about coding or chat with the community and help others.
Sign up now!