Lifetime of a temporary bound to a reference

  • Permalink
  • submit to reddit
  • Email
  • Follow


I'm not sure what the standard says about a case like this (mainly per
12.2/5):

class B {};
class D1: public B {};
class D2: public B {};

void foo( bool r )
{
	B const& a = ( r ? D1() : D2() );
	// Does the temporary live here?
}

itaj

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

0
Reply itaj 6/27/2010 8:27:25 AM

See related articles to this posting

itaj sherman wrote:

> I'm not sure what the standard says about a case like this (mainly per
> 12.2/5):
> 
> class B {};
> class D1: public B {};
> class D2: public B {};
> 
> void foo( bool r )
> {
> B const& a = ( r ? D1() : D2() );
> // Does the temporary live here?
> }
> 

First of all, that code isn't valid. Let's change it to

    B const& a = ( r ? B() : D2() );

"Temporary" is a property of objects and strictly according to standards the
lifetime of it should be lengthened. But the aim of the Standard is that
only "direct" references to temporaries are lifetime-extended. What such a
"direct" reference is, however, isn't specified by the Standard as far as i
know.

In your example, even tho the result is an rvalue that definitely refers to
a temporary, that rvalue refers *either* a temporary coming from the left
*or* from the right side. Thus there is no direct reference anymore, in some
sense.

The issue around ?: and temporaries is subject of http://www.open-
std.org/jtc1/sc22/wg21/docs/cwg_active.html#462 . The direction that #462
drives toward is making "temporary" a property of expressions, instead of a
property of objects, without explicitly mentioning it in that issue report.
That issue report is the only place i know that would attribute it to
expressions explicitly. Many places in the Standard already seem to assume
that, while the text in the Standard is clear that it is a property of
objects.

To me it seems the following solves these questions too, with much less
overhead:

- Say that lifetime extension rules only apply to temporaries that haven't
been bound to references or to the implicit object parameter yet.

This is sort of what the RVO rules do, saying that they only apply to
temporaries that haven't yet been bound to references. I suspect here is a
reason they haven't done this way, but i can't think of a reason.

This would allow the above conditional-expression be lifetime extended too.
It still disallows extending lifetime of a "*this" refering to a temporary
object and other such things, which is the aim of the Standard. It would
keep the term "temporary" to strictly name a property of objects.

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

0
Reply Johannes 6/28/2010 1:37:54 PM

itaj sherman wrote:

> I'm not sure what the standard says about a case like this (mainly per
> 12.2/5):
> 
> class B {};
> class D1: public B {};
> class D2: public B {};
> 
> void foo( bool r )
> {
> B const& a = ( r ? D1() : D2() );
> // Does the temporary live here?
> }
> 

I'm sorry to annoy you again, but i've just noticed that the issue report
link i gave was discussing the comma operator instead of the conditional
operator (omg, epic fail).  It turns out from links in that issue report
that the issue with the conditional operator has been fixed in C++0x by
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#446 . It
provides the "direct reference" i talked about.

Looking at it again, i found an interesting similarity with bit-fields: An
object can be a bit-field, but an expression can be a bit-field likewise.
Like, it's said "the result is of that type and value category and it is a
bit-field if ..." at 5.16/4 in the FCD. If it would omit the addendum, the
expression would potentially refer to a bit-field, but won't be a bit-field
itself. This seems to be exactly like the situation with temporaries. The
lifetime-lengthening subsection refers to the expression property, thus it
doesn't care about lvalues that refer to temporaries, because those lvalues
won't have the "temporary" property be true. But now, i'm just more confused
how these things fit together, really :(

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

0
Reply Johannes 6/28/2010 1:39:00 PM

On Jun 27, 5:27 pm, itaj sherman <itajsher...@gmail.com> wrote:
> I'm not sure what the standard says about a case like this (mainly per
> 12.2/5):
>
> class B {};
> class D1: public B {};
> class D2: public B {};
>
> void foo( bool r )
> {
>         B const& a = ( r ? D1() : D2() );
>         // Does the temporary live here?
>
> }

AFAIK, it does. E.g. ScopeGuard of Petru/Alexandrescu uses that
language feature.

Goran.


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

0
Reply Goran 6/28/2010 1:39:59 PM

On 27 June, 17:27, itaj sherman <itajsher...@gmail.com> wrote:
> I'm not sure what the standard says about a case like this (mainly per
> 12.2/5):
>
> class B {};
> class D1: public B {};
> class D2: public B {};
>
> void foo( bool r )
> {
>         B const& a = ( r ? D1() : D2() );
>         // Does the temporary live here?
>
> }


Hi, the temporary in such a case lives as long as the reference does.
Have a look at this article:
http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/

Your example however will not compile, because operator ?: is not that
clever to deduce that you mean the common base type. You have to cast
at least one of the operands explicitly:

  B const& a =  r ? static_cast<B&>( D1() ): D2();

Regards,
&rzej

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

0
Reply restor 6/28/2010 1:52:01 PM

On Jun 27, 6:27 pm, itaj sherman <itajsher...@gmail.com> wrote:
> I'm not sure what the standard says about a case like this (mainly per
> 12.2/5):
> 
> class B {};
> class D1: public B {};
> class D2: public B {};
> 
> void foo( bool r )
> {
>         B const& a = ( r ? D1() : D2() );

//original code doesn't compile, it should have been:
B const& a = ( r ? static_cast<B const&>(D1()) : static_cast<B
const&>(D2()) );
//or:
B const& a = ( r ? B() : D2 );

>        // Does the temporary live here?

//would that change the answer?


> 
> }
> 
> itaj
> 

itaj


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

0
Reply itaj 6/28/2010 6:29:16 PM
comp.lang.c++.moderated 10592 articles. 6 followers. Post

5 Replies
144 Views

Similar Articles

[PageSpeed] 9

  • Permalink
  • submit to reddit
  • Email
  • Follow


Reply:

Similar Artilces:

Lifetime of a temporary that is bound to a reference
Hello, I vaguely remember that when a temporary is bound to a reference, the lifetime of the temporary is at least as long as that of the reference. I would like to know how this is defined in the following case: const int& min( const int& a, const int& b ) { return a < b ? a : b; } int f() { return 42; } int main() { int i = min( f(), int() ); return 0; } In the example above, two temporaries are bound to the formal parameters of min(). One of these parameters is then bound to the return value of the function, which is then used to assign a value to 'i'....

lifetime of temporaries bound to references
Given a following function: template <typename T> T const & dummy(T const & in) { return in; } will the following code produce a dangling reference: int const & cr = dummy(5); ??? Reading the wording of the latest draft for C++0x it looks like it will. [12.1] clause 5, second condition. Was it the case for c++03 as well? Thanks, Andy. -- [ comp.std.c++ is moderated. To submit articles, try just posting with ] [ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu] [ --- Please see the FAQ before posting. ---...

Lifetime of a temporary bound to a reference through an operator ? :
int main(int argc, char** argv) { std::istream& is = (argc < 2) ? std::cin : std::ifstream(argv[1]); read_some(is); read_more(is); // ... } Should this work? Can we say that the std::ifstream temporary object is bound to the temporary 'is'? If yes, 12.2/5 will allow the temporary to persist until the end of the scope, and otherwise, it will be destroyed after the evaluation of the full expression, i.e. "(argc < 2) ? std::cin : std::Ifstream(argv[1])", as specified by 12.2/3. GCC 3.3.1 seems to apply 12.2/3 here. If this shouldn't work, ...

Lifetime of temporaries bound to references in C++11
I noticed an unexpected order of destructor calls for temporaries bound to references wrt the lifetime of the enclosing object when experimenting with C++11 using gcc 4.9.0. In particular, the program included below produced the output done ~C ~B ~D which is counter to my expectation of done ~D ~C ~B Looking at the C++11 standard, 12.2p5 clearly requires ~C to be called before ~B (reverse order of completion of construction). However, the ordering of object vs. temporary is specified wrt. the moment the object/temporary is created. Searching the stan...

"lifetime of temporary bound to reference..."
Hello, Does the rule in the subj applies to the following: std::pair<int, int> getPair() { return std::pair<int, int>(1, 2); } int main() { // is this legal? const std::pair<int, int> &p1 = getPair(); // and this? std::pair<int, int> &p2 = getPair(); std::cout << p1.first << p2.second; } Igor R. wrote: > Does the rule in the subj applies to the following: > > std::pair<int, int> getPair() > { > return std::pair<int, int>(1, 2); > } > > int main() > { > // is this legal? > const std:...

case of extended lifetime of temporary bound to reference
Does clause 12.2/5 apply to const reference x below? Or in other words: is behaviour of this program well defined? #include <cstdio> struct Y { int x; Y(int i) : x(i) {} }; int main() { const int& x = Y(20).x; std::printf("%i\n", x); // x is still vallid ? } Thanks B. --- [ 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....

Temporaries, references, lifetimes and const_cast
I know this subject comes up a lot - and I've got the gist of it - but there is one particular case that I can't work through. Is it legal or not? This has come up before: <code> std::string Func() { return "monkey"; } int main() { const std::string &cstr = Func(); std::string &str = const_cast<std::string &>(cstr); str = "ape"; } </code> and the Jury seems to be out still. But I want to do something even nastier: <code> #include <string> #include <iostream> std::string Func() { return "monkey&...

Object lifetimes when bound to references
Hello, during a discussion on a C++ internet forum, some question came up regarding references and the lifetime of the objects they alias. I can't find any clear wording on that in the draft standard. Example 12.2 in the standard document illustrates that temporaries bound to references-to-const live as long as the reference does. But does it e.g. matter if the temporary was created in scope of a function body and has to outlive the function call? And what happens with this temporary when everything else from the stack has to be destroyed except the temporary? Is it copied to a new...

Hiding const references bound to temporary
Hi All, Given the following code : char const & identity( char const &c ) { return c; } char const & f( ) { return identity('A'); } char const & g( ) { return 'A'; } Of course, the compiler complains of function 'g' returning a reference to a temporary. But the compiler (I used gcc 4.2.x) doesn't say anything regarding the function 'f'. I know that temporaries bound to constant references have a life span that extends to the expression in which the function call where the bounding took place is evaluated. Now given that, is the f...

About const reference bounding to temporary variables.
Hi, folks, Look at the following snippet: int main() { double temp = 2.0; const double& r = 2.0 + temp; // without const, an err will be raised return 0; } As the comment block illustrated, without "const" qualifier error: could not convert `(temp + 2.0e+0)' to `double&' will be raised, I know, you can't use an expression to initialize a reference, but why it's OK with const qualifier? Thanks, you guys. 刘昊 wrote: > Hi, folks, > Look at the following snippet: > > int main() > { > double temp = 2.0; > const double& ...

temporary bounded to reference param in function...
Hi all, I just want to clarify this example: #include <memory> struct X { virtual std::auto_ptr<X> clone() const; //etc... }; struct Y { virtual std::auto_ptr<Y> clone() const; //etc... }; template <class T> class Opt { public: Opt( const T& ref ): p_( &ref ){ } std::auto_ptr<T> clone( T* ) const { return p_->clone(); } private: const T* p_; }; struct OptXY : Opt<X>, Opt<Y> { OptXY( const X& x, const Y& y ) : Opt<X>( x ), Opt<Y>( y ){ } }; void foo( const Opt<X>&, const Opt&...

Simple question: extending lifetime of temporaries with a reference
I've heard of "extending the lifetime of a temporary by binding it to a reference", but am not entirely sure of when that applies. My impression is that if you do, say: // sample 1 std::string str1( "String 1\n"); std::string str2( "string 2\n"); std::string &str_sum = str1 + str2; std::cout << str_sum << str::endl; then the temporary object "str1 + str2" won't be destroyed until str_sum goes out of scope. On the other hand, I'm fairly convinced that // sample 2 std::string &f() { st...

A reference to non-const to be bound to a temporary object
Hello: I'm not sure how to word this question properly, so I'll start by listing the code I am having problems with: int main() { std::vector<int> x; x.swap(std::vector<int>()); return 0; } This is also not allowed: std::vector<int> get() { return std::vector<int>(); } int main() { std::vector<int> x; x.swap(get()); return 0; } I was told on another newsgroup that the following code is nonstandard C++. The reason being that "Standard C++ doesn't allo...

Lifetime of temporary bound to aggregate initialized struct member
(I originally asked this on stackoverflow (http://stackoverflow.com/q/ 5719636/6210)) Given the following code: class foo { }; class bar: public foo { public: ~bar() { printf("~bar()\n"); } }; class zab: public foo { public: ~zab() { printf("~zab()\n"); } }; struct foo_holder { const foo &f; }; int main() { foo_holder holder[]= { {bar()}, {zab()} }; printf("done!\n"); return 0; } the output is: ~bar() ~zab() done!...

Re: Lifetime of temporary bound to aggregate initialized struct member
[Second attempt after ~24 h] Am 21.04.2011 23:01, schrieb Mat Noguchi: > [..] > > Given the following code: > > class foo > { > }; > > class bar: public foo > { > public: > ~bar() { printf("~bar()\n"); } > }; > > class zab: public foo > { > public: > ~zab() { printf("~zab()\n"); } > }; > > struct foo_holder > { > const foo&f; > }; > > int main() > { > foo_hold...

Reference to temporary
Hello all, The code below is not legal (problem with the foo_t initializer list) because: "A reference that is not to 'const' cannot be bound to a non-lvalue" How can I best achieve an effect similar to what this code attempts? Thanks, Dave class bar_t { }; class foo_t { public: foo_t(): ref(bar_t()) {} private: bar_t &ref; }; void foo() { foo_t a; } int main() { foo(); return 0; } "Dave" <better_cs_now@yahoo.com> wrote in message news:vqj391em2v3s19@news.supernews.com... > Hello all, > > The code below is...

Lifetime of temporaries?
I should know this, but ... Is this code safe? std::string foo(); std::printf("%s", foo().c_str()); Or is my temporary std::string destroyed before printf() is done with it? Background: I'm sitting with a whole bunch of classes and (for now) only a printf-like interface for printing logs/debug info. I was thinking about - implementing ostream << foo as usual, - have a 'template<T> std:string to_string(const T&)' based on it - log using the slightly ugly syntax log("error in %s: %s", to_string(foo).c_str(), to_string(bar...

reference lifetimes...
Here is my code: #include <iostream> struct foo { foo() { std::cout << this << "->foo::foo()" << std::endl; } ~foo() { std::cout << this << "->foo::~foo()" << std::endl; } }; struct foo_holder { foo const& m_ref; }; int main() { { foo_holder fh = { foo() }; std::cout << "okay" << std::endl; } std::cout << std::endl; { foo const&am...

lifetime of temporaries
Hi! Note: I'm not 100% sure the term temporaries is right. However, here is the code which I'm referring to: std::string function1() { return "fubar"; } std::string function2() { std::string const& str = function1();// XXX std::fstream stream; } At the position XXX, I'm binding a temporary to a const reference. As far as I know, this should extend the lifetime of the temporary to that of the scope of the reference. However, it seems as if one of my compilers (VC7) doesn't do that. The construction of the fstream partially overwrites the the memory of t...

lifetime of temporaries
Rather a long program I'm afraid but I don't think I can cut it down any further. What I'm trying to do is construct a complex object Y from several X objects in a complex expression. I'm trying to do this without creating any temporaries of Y. To do that I'm defined a number of proxy classes which contain references to the arguments in the expression. All the proxies define a conversion operator to Y which will ultimately be used to create the Y object. The issue for me is whether I'm guaranteed that all the temporaries will still exist when the conversion happens. He...

Is binding non-const references to temporaries the sole key feature of rvalue references?
Hello Group! Is the ability to bind a non-const reference to a temporary the only important feature / benefit of rvalue references? Please note, I am not asking what it is that rvalue references let you do; I am asking what specific capability of rvalue references lets you do those things. Asked another way, if we were to permit regular non-const references to bind to temporaries (I'm not saying we should.), would there remain any need to introduce rvalue references into the language? Basic illustration: // int& nr = 1; // illegal: non-const reference to t...

reverse_iterator reference to temporary?
I am looking at a g++ (3.2.2) implimentation of the reverse_iterator iterator adaptor, and it looks to me like operator[](difference_type) returns a reference to a temporary: .... reference operator[](difference_type __n) const { return *(*this + __n); } .... reverse_iterator operator+(difference_type __n) const { return reverse_iterator(current - __n); } .... reference operator*() const { _Iterator __tmp = current; return *--__tmp; } where reference is: typedef typename iterator_traits<_Iterator>::reference reference; and _Iterator is the type of the iterator being adapted. ...

Hiding a reference to temporary
Hi All, I was playing around with code (the code did consent) and stumbled over this : #include <iostream> char const & hideConstRefToTemporary( char const &c ) { return c; } char const & getChar1( ) { return hideConstRefToTemporary('A'); } char const & getChar2( ) { return 'A'; } int main( ) { std::cout << getChar() << "\n"; std::cout << getChar2() << "\n"; return 0; } If you try and compile this code with ...

lifetime of const references...
Here is the code which should compile fine; program output and my question follows: ____________________________________________________________________ #include <cstdio> namespace func_ptr { namespace sys { typedef void (callback_type) (void const* const); class base_pod { protected: callback_type* mp_callback; public: void execute() const { mp_callback(this); } }; template<typename T, typename T_mfptr, typename T_p1> class param_1 : public base_pod{ T m_obj; T_mfptr m_mfptr; T_p1 m_p1; public: ...