Topic: Lifetime of temporaries


Author: Martin Sebor <sebor@roguewave.com>
Date: Wed, 25 Apr 2001 05:11:42 GMT
Raw View
brian.hanley@colorado.edu wrote:
>
> Hi All,
>
> It is my understanding that if assigned to a constant reference,
> a temporary object is required to persist until that reference
> goes out of scope.
>
> What if that constant reference is assigned to a second constant
> reference? Is the temporary object required to persist until that
> second reference goes out of scope?
>
> This can occur when the second reference is a member of an object:
>
> #include <iostream>
> using namespace std;
>
> class A
> {
>    public:
>     A() { cout << "A::ctor" << endl; }
>    ~A() { cout << "A::dtor" << endl; }
> };
>
> class Ref
> {
>    public:
>     Ref(const A& theRef): myRef(theRef) { cout << "Ref::ctor" << endl; }
>    ~Ref()                               { cout << "Ref::dtor" << endl; }
>
>    private:
>    const A& myRef;
> };
>
> int main()
> {
>    Ref aRef = A();
>    cout << "aRef has not been destroyed yet." << endl;
>
>    return 0;
> }
>
> With g++ 2.95.2, I get the following output:
>
> A::ctor
> Ref::ctor
> A::dtor
> aRef has not been destroyed yet.
> Ref::dtor
>
> Is g++ compliant with the standard in this case?

I think it is. I believe the answer is in 12.2, p5:

"... A temporary bound to a reference member in a constructor's
ctor-initializer (12.6.2) persists until the constructor exits. A temporary
bound to a reference parameter in a function call (5.2.2) persists until
the completion of the full expression containing the call. ..."

>
> Is the temporary required to persist once the statement
> "Ref aRef = A();" has been executed?

I don't believe so.

Regards
Martin

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "C. M. Heard" <heard@vvnet.com>
Date: Wed, 25 Apr 2001 05:16:39 GMT
Raw View
Steve Clamage wrote:
[ ... ]
> > class Ref
> > {
> >    public:
> >     Ref(const A& theRef): myRef(theRef) { cout << "Ref::ctor" << endl; }
> >    ~Ref()                               { cout << "Ref::dtor" << endl; }
> >
> >    private:
> >    const A& myRef;
> > };
> >
> > int main()
> > {
> >    Ref aRef = A();
>
> Here you use a temporary A object to initialize the formal parameter
> of the Ref constructor. The temp A object is required to exist
> until the formal parameter's lifetime ends. That lifetime ends
> when the Ref constructor returns. You are left with a dangling
> reference inside the Ref object. That is one reason not to use
> references as members of classes.

I don't agree with that last statement.  I would say rather that the
lesson is that one should neither use a const reference formal parameter
to initialize a const reference member nor take the address of such a
parameter to initialize a pointer to const member.  I've had occasion
to use const reference members in the past, and in those cases I have
used either a pointer to const formal parameter or a non-const reference
formal parameter to initialize such members.  The choice hinges upon
whether the object to be bound was itself const or not;  where possible,
the non-const reference parameter is preferred.

Thus, one could fix the code fragment above this way:

    class Ref
    {
       public:
        Ref(const A *pA): myRef(*pA) { cout << "Ref::ctor" << endl; }
       ~Ref()                        { cout << "Ref::dtor" << endl; }

       private:
       const A& myRef;
    };

    int main()
    {
       const A theA;
       Ref aRef(&theA);
       // ...

or this way:

    class Ref
    {
       public:
        Ref(A& theRef): myRef(theRef) { cout << "Ref::ctor" << endl; }
       ~Ref()                         { cout << "Ref::dtor" << endl; }

       private:
       const A& myRef;
    };

    int main()
    {
       A theA;
       Ref aRef(theA);
       // ...

Mike

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: Steve Clamage <stephen.clamage@sun.com>
Date: Thu, 26 Apr 2001 20:36:34 GMT
Raw View
Brian Hanley wrote:
>
> "Steve Clamage" <stephen.clamage@sun.com> wrote in message
> news:3AE5E3CA.A0A872DC@sun.com...
> > Here you use a temporary A object to initialize the formal parameter
> > of the Ref constructor. The temp A object is required to exist
> > until the formal parameter's lifetime ends. That lifetime ends
> > when the Ref constructor returns. You are left with a dangling
> > reference inside the Ref object. That is one reason not to use
> > references as members of classes.
> >
> > --
> > Steve Clamage, stephen.clamage@sun.com
>
> As with so many other aspects of the C++ language, ease of implementation
> seems
> to have been the determining factor insofar as lifetime of temporaries is
> concerned.

Not at all. Ease of implementation has almost never been a consideration
in any C++ feature. Many C++ features are very difficult to implement.
The consideration has been *possibility* of implementation, and the
likely effect on users.

For example, if no one knows how to implement a feature, it should not
be part of the standard. (Sound obvious, but it's sometimes hard to
convince people that just wanting something badly doesn't make it possible.)

Some features could be implemented, but either the expense was too great
for the benefit gained, or all users would have to pay for an expensive
feature even if they didn't use it. D&E has examples.

In the case of this particular feature of lifetime of temporaries, the
requested feature cannot be implemented. The compiler would have to
determine at compile time when the last reference to an object would
go out of scope at run time. That isn't possible, in theory or in
practice. The only way to ensure in general that a temp lasts long
enough is to save destruction until the end of the program.

If you want to pass around references to an object, don't use a temp.
Use an object with a lifetime that will be long enough.

--
Steve Clamage, stephen.clamage@sun.com

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: Michiel Salters<Michiel.Salters@cmg.nl>
Date: Fri, 27 Apr 2001 23:05:32 GMT
Raw View
In article <3AE71ED6.58D17D20@sun.com>, Steve Clamage says...
>
>Brian Hanley wrote:
>>
>> "Steve Clamage" <stephen.clamage@sun.com> wrote in message
>> news:3AE5E3CA.A0A872DC@sun.com...
>> > Here you use a temporary A object to initialize the formal parameter
>> > of the Ref constructor. The temp A object is required to exist
>> > until the formal parameter's lifetime ends. That lifetime ends
>> > when the Ref constructor returns. You are left with a dangling
>> > reference inside the Ref object. That is one reason not to use
>> > references as members of classes.
>> >
>> > --
>> > Steve Clamage, stephen.clamage@sun.com
>>
>> As with so many other aspects of the C++ language, ease of implementation
>> seems to have been the determining factor insofar as lifetime
>> of temporaries is concerned.

[ SNIP ]

>Some features could be implemented, but either the expense was too great
>for the benefit gained, or all users would have to pay for an expensive
>feature even if they didn't use it. D&E has examples.
>
>In the case of this particular feature of lifetime of temporaries, the
>requested feature cannot be implemented. The compiler would have to
>determine at compile time when the last reference to an object would
>go out of scope at run time. That isn't possible, in theory or in
>practice. The only way to ensure in general that a temp lasts long
>enough is to save destruction until the end of the program.

>--
>Steve Clamage, stephen.clamage@sun.com

I'm not sure about your claim that "The compiler would have to
determine at compile time when the last reference would go out
of scope at run time." Why must the compiler determine that?

If references are implemented using a smart pointer, they could
at run-time determine such things. This would of course bring
with it a large inefficiency for many simple cases, so I'm not
advocating such a change. I do think that it is possible in
theory, though.

I realised this because I once considered the result of
implementing a smart pointer class using only a reference. If
references would work like the OP, this reference would
cause garbage collection of its object when the last smart
pointer is destructed. Ergo, that would have forced garbage
collection on C++ via a backdoor.

Regards,

--
Michiel Salters
Consultant Technical Software Engineering
CMG Trade, Transport & Industry
Michiel.Salters@cmg.nl

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: brian.hanley@colorado.edu
Date: Mon, 23 Apr 2001 20:38:57 GMT
Raw View
Hi All,

It is my understanding that if assigned to a constant reference,
a temporary object is required to persist until that reference
goes out of scope.

What if that constant reference is assigned to a second constant
reference? Is the temporary object required to persist until that
second reference goes out of scope?

This can occur when the second reference is a member of an object:

#include <iostream>
using namespace std;

class A
{
   public:
    A() { cout << "A::ctor" << endl; }
   ~A() { cout << "A::dtor" << endl; }
};

class Ref
{
   public:
    Ref(const A& theRef): myRef(theRef) { cout << "Ref::ctor" << endl; }
   ~Ref()                               { cout << "Ref::dtor" << endl; }

   private:
   const A& myRef;
};

int main()
{
   Ref aRef = A();
   cout << "aRef has not been destroyed yet." << endl;

   return 0;
}

With g++ 2.95.2, I get the following output:

A::ctor
Ref::ctor
A::dtor
aRef has not been destroyed yet.
Ref::dtor

Is g++ compliant with the standard in this case?

Is the temporary required to persist once the statement
"Ref aRef = A();" has been executed?

Brian


 -----  Posted via NewsOne.Net: Free (anonymous) Usenet News via the Web  -----
  http://newsone.net/ -- Free reading and anonymous posting to 60,000+ groups
   NewsOne.Net prohibits users from posting spam.  If this or other posts
made through NewsOne.Net violate posting guidelines, email abuse@newsone.net

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: Steve Clamage <stephen.clamage@sun.com>
Date: Tue, 24 Apr 2001 20:37:10 GMT
Raw View
brian.hanley@colorado.edu wrote:
>
> It is my understanding that if assigned to a constant reference,
> a temporary object is required to persist until that reference
> goes out of scope.

Not "assigned", but "initialized".

>
> What if that constant reference is assigned to a second constant
> reference?  Is the temporary object required to persist until that
> second reference goes out of scope?

No. In general, it would not possible for the compiler to determine
what the lifetime should be. In particular, the passing along of a
reference could happen in a different translation unit.

>
> This can occur when the second reference is a member of an object:
>
> #include <iostream>
> using namespace std;
>
> class A
> {
>    public:
>     A() { cout << "A::ctor" << endl; }
>    ~A() { cout << "A::dtor" << endl; }
> };
>
> class Ref
> {
>    public:
>     Ref(const A& theRef): myRef(theRef) { cout << "Ref::ctor" << endl; }
>    ~Ref()                               { cout << "Ref::dtor" << endl; }
>
>    private:
>    const A& myRef;
> };
>
> int main()
> {
>    Ref aRef = A();

Here you use a temporary A object to initialize the formal parameter
of the Ref constructor. The temp A object is required to exist
until the formal parameter's lifetime ends. That lifetime ends
when the Ref constructor returns. You are left with a dangling
reference inside the Ref object. That is one reason not to use
references as members of classes.

--
Steve Clamage, stephen.clamage@sun.com

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "Andrea Ferro" <AndreaF@UrkaDVD.it>
Date: Tue, 24 Apr 2001 23:27:04 GMT
Raw View
<brian.hanley@colorado.edu> wrote in message
news:9c23p1$q1p$1@news.netmar.com...
> Hi All,
>
> It is my understanding that if assigned to a constant reference,
> a temporary object is required to persist until that reference
> goes out of scope.

Correct.

> What if that constant reference is assigned to a second constant
> reference? Is the temporary object required to persist until that
> second reference goes out of scope?

No.

> This can occur when the second reference is a member of an object:
... snip ...
> Is g++ compliant with the standard in this case?

Yes

> Is the temporary required to persist once the statement
> "Ref aRef = A();" has been executed?

No. It was bound to the parameter, and the parameter is gone.

--

Andrea Ferro

---------
Brainbench C++ Master. Scored higher than 97% of previous takers
Scores: Overall 4.46, Conceptual 5.0, Problem-Solving 5.0
More info http://www.brainbench.com/transcript.jsp?pid=2522556



---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr>
Date: Tue, 24 Apr 2001 23:27:18 GMT
Raw View
Steve Clamage <stephen.clamage@sun.com> writes:

[...]

| That is one reason not to use references as members of classes.

The same analysis applies for a "const T*".  Is that a sufficient
reason not to use const T* as members of classes.

--
Gabriel Dos Reis, dosreis@cmla.ens-cachan.fr


---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "Brian Hanley" <brian.hanley@level3.com>
Date: Tue, 24 Apr 2001 23:49:03 GMT
Raw View
"Steve Clamage" <stephen.clamage@sun.com> wrote in message
news:3AE5E3CA.A0A872DC@sun.com...
> Here you use a temporary A object to initialize the formal parameter
> of the Ref constructor. The temp A object is required to exist
> until the formal parameter's lifetime ends. That lifetime ends
> when the Ref constructor returns. You are left with a dangling
> reference inside the Ref object. That is one reason not to use
> references as members of classes.
>
> --
> Steve Clamage, stephen.clamage@sun.com

As with so many other aspects of the C++ language, ease of implementation
seems
to have been the determining factor insofar as lifetime of temporaries is
concerned.

That has unfortunate repercussions in terms of implicit conversion and
"knows-a"
relationships:

class Buffer
{
   public:
   Buffer(ifstream&);
   // ...
};

class MyClass
{
   public:
   MyClass(const Buffer& theBuffer, ...): myBuffer(theBuffer), // ...
   // ...

   private:
   // ...
   const Buffer& myBuffer;
};

int main()
{
   // ...

   ifstream aStream("someFile");
   MyClass anInstance(aStream); // The instance is going to hold a reference
to a non-existent buffer.

   // ...
   return 0;
}

In this short example, the temporary "Buffer" object will be destroyed as
soon as "anInstance" is
initialized. There are ways around this situation, of course, such as
declaring the "Buffer" constructor
as "explicit", but it would be nice to have the temporary persist ...

Brian



---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: kanze@us-es.sel.de (James Kanze)
Date: 14 Dec 1993 13:03:47 GMT
Raw View
In article <1993Dec11.183721.8591@borland.com> pete@borland.com (Pete
Becker) writes:

|> In article <rfgCHv7C1.8yo@netcom.com>,
|> Ronald F. Guilmette <rfg@netcom.com> wrote:
|> >In article <2e828m$cq0@nwfocus.wa.com> rrowe@halcyon.com (Robin Rowe) writes:

|> >>Are explicitly declared anonymous objects temporaries?

|> >>If I have something like this:

|> >> int main()
|> >> {   Object(1);
|> >>     Object x(2);
|> >>     return 0;
|> >> }

|> >>Is Object(1) a temporary, and therefore its dtor may be called before
|> >>the ctor for Object x(2)?

|> >No.  `Object(1)' is a syntax error.

|>  Object(1) is not a syntax error nor is it a semantic error. It is an
|> explicit conversion of the value 1 to an object of type Object. The resulting
|> object is not used. It's no different from

|>  1;

|> which is legal but pointless. The conversion to Object may not be pointless
|> if the constructor or the destructor has side effects.

And to answer the original question: according to the current draft of
the working papers, the temporary Object(1) *will* be destructed
before the constructor for x is called.  Current compilers vary, but I
think in most cases (except Cfront), it will also be destructed before
the constructor to x is called.
--
James Kanze                             email: kanze@us-es.sel.de
GABI Software, Sarl., 8 rue du Faisan, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                   -- Beratung in industrieller Datenverarbeitung




Author: rfg@netcom.com (Ronald F. Guilmette)
Date: Fri, 17 Dec 1993 09:49:18 GMT
Raw View
In article <rfgCHv7C1.8yo@netcom.com> rfg@netcom.com (Ronald F. Guilmette) writes:
>In article <2e828m$cq0@nwfocus.wa.com> rrowe@halcyon.com (Robin Rowe) writes:
>>
>>Are explicitly declared anonymous objects temporaries?
>>
>>If I have something like this:
>>
>> int main()
>> {   Object(1);
>>     Object x(2);
>>     return 0;
>> }
>>
>>Is Object(1) a temporary, and therefore its dtor may be called before
>>the ctor for Object x(2)?
>
>No.  `Object(1)' is a syntax error.

Sorry.  Sorry. Sorry.

I have been corrected.  I misspoke.  The above is *valid*.  There is no
syntax error.

--

-- Ronald F. Guilmette, Sunnyvale, California -------------------------------
------ domain address: rfg@netcom.com ---------------------------------------
------ uucp address: ...!uunet!netcom.com!rfg -------------------------------




Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: Wed, 8 Dec 1993 14:11:49 GMT
Raw View
fenster@shadow.cs.columbia.edu (Sam Fenster) writes:


>What's the chance that the lifetime of temporaries will be lengthened in the
>new standard?
[...]
>It would be ideal if temporaries were preserved until the containing
>expression (or the containing statement) had finished executing.

I believe that the committee has already decided that temporaries
must be destroyed "at end of full expression" (a full expression is
an expression not enclosed in any other expression).  I'm not sure
about exactly what they decided for ?:, &&, || and comma expressions,
though - there might be different rules for those.

--
Fergus Henderson                     fjh@munta.cs.mu.OZ.AU




Author: kanze@us-es.sel.de (James Kanze)
Date: 09 Dec 1993 11:47:35 GMT
Raw View
In article <9334301.4509@mulga.cs.mu.OZ.AU> fjh@munta.cs.mu.OZ.AU
(Fergus Henderson) writes:

|> fenster@shadow.cs.columbia.edu (Sam Fenster) writes:

|> >What's the chance that the lifetime of temporaries will be lengthened in the
|> >new standard?
|> [...]
|> >It would be ideal if temporaries were preserved until the containing
|> >expression (or the containing statement) had finished executing.

|> I believe that the committee has already decided that temporaries
|> must be destroyed "at end of full expression" (a full expression is
|> an expression not enclosed in any other expression).  I'm not sure
|> about exactly what they decided for ?:, &&, || and comma expressions,
|> though - there might be different rules for those.

There aren't.

Such special rules make the language harder to learn and harder to
use.  Their only justification was based on implementation issues.
The users won.
--
James Kanze                             email: kanze@us-es.sel.de
GABI Software, Sarl., 8 rue du Faisan, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                   -- Beratung in industrieller Datenverarbeitung




Author: rrowe@halcyon.com (Robin Rowe)
Date: 9 Dec 1993 12:36:38 -0800
Raw View
Are explicitly declared anonymous objects temporaries?

If I have something like this:

 int main()
 {   Object(1);
     Object x(2);
     return 0;
 }

Is Object(1) a temporary, and therefore its dtor may be called before
the ctor for Object x(2)?

--
-----------------------------------------------------------
Robin Rowe    Rowe Techology |   Flamers and complainers:
rrowe@halcyon.com            |    If you have nothing to
Northwest C++ Users Group    |     contribute please don't.




Author: rfg@netcom.com (Ronald F. Guilmette)
Date: Sat, 11 Dec 1993 09:50:25 GMT
Raw View
In article <2e828m$cq0@nwfocus.wa.com> rrowe@halcyon.com (Robin Rowe) writes:
>
>Are explicitly declared anonymous objects temporaries?
>
>If I have something like this:
>
> int main()
> {   Object(1);
>     Object x(2);
>     return 0;
> }
>
>Is Object(1) a temporary, and therefore its dtor may be called before
>the ctor for Object x(2)?

No.  `Object(1)' is a syntax error.

--

-- Ronald F. Guilmette, Sunnyvale, California -------------------------------
------ domain address: rfg@netcom.com ---------------------------------------
------ uucp address: ...!uunet!netcom.com!rfg -------------------------------




Author: pete@borland.com (Pete Becker)
Date: 11 Dec 93 18:37:21 GMT
Raw View
In article <rfgCHv7C1.8yo@netcom.com>,
Ronald F. Guilmette <rfg@netcom.com> wrote:
>In article <2e828m$cq0@nwfocus.wa.com> rrowe@halcyon.com (Robin Rowe) writes:
>>
>>Are explicitly declared anonymous objects temporaries?
>>
>>If I have something like this:
>>
>> int main()
>> {   Object(1);
>>     Object x(2);
>>     return 0;
>> }
>>
>>Is Object(1) a temporary, and therefore its dtor may be called before
>>the ctor for Object x(2)?
>
>No.  `Object(1)' is a syntax error.
>

 Object(1) is not a syntax error nor is it a semantic error. It is an
explicit conversion of the value 1 to an object of type Object. The resulting
object is not used. It's no different from

 1;

which is legal but pointless. The conversion to Object may not be pointless
if the constructor or the destructor has side effects.
 -- Pete




Author: rrowe@halcyon.com (Robin Rowe)
Date: 11 Dec 1993 13:10:36 -0800
Raw View
//tempobj.cpp
//Robin Rowe

#include <iostream.h>

class Object
{  int x;
public:
   Object(const int x)
   :   x(x)
   {   cout<<"Object "<<x<<" ctor\n";
   }
   ~Object()
   {   cout<<"Object "<<x<<" dtor\n";
}  };

int main()
{  Object(1);
   Object x(2);
   return 0;
--
-----------------------------------------------------------
Robin Rowe    Rowe Techology |   Flamers and complainers:
rrowe@halcyon.com            |    If you have nothing to
Northwest C++ Users Group    |     contribute please don't.




Author: dag@control.lth.se (Dag Bruck)
Date: 7 Dec 1993 07:23:04 GMT
Raw View
In <comp.std.c++> fenster@shadow.cs.columbia.edu (Sam Fenster) writes:
>
>It would be ideal if temporaries were preserved until the containing
>expression (or the containing statement) had finished executing.

I the C++ standardization committees decided on that, last July.




Author: fenster@shadow.cs.columbia.edu (Sam Fenster)
Date: 06 Dec 1993 21:25:32 GMT
Raw View
What's the chance that the lifetime of temporaries will be lengthened in the
new standard?

It's very inconvenient that I can't have an "accessor" function which takes an
object and returns a const ref to a member, or to allocated data.  Currently,
if the arg is a temp, it (and the data) may be destroyed the moment the
accessor returns, making the returned reference useless.  And it may be very
inefficient to return member data by value.

It would be ideal if temporaries were preserved until the containing
expression (or the containing statement) had finished executing.