Topic: Lifetime of Temporaries


Author: Andrew D Jewell <avjewe@kaizen.net>
Date: 1997/07/25
Raw View
I have a subtle question about the lifetime of temporaries.
As you see in the class String below, the result of
operator const char* becomes invalid after the String is destroyed.
I can't quite tell from the CD2 spec if either of my two examples
are guarenteed to be OK.

12.2.3 states that temporaries aren't destroyed until the end of the
"full expression".

1.8.13 states that a "full expression" is an expression that is
not a sub expression of another expression.

My best guess is that my first example is OK, but my second
example is not.

Can anyone confirm or deny this?

class String
{
   public:
      String(const char* s) {_str = strdup(s);}
      operator const char*() const {return _str;}
      friend String operator+(const String& left, const String& right);
      ~String() {free(_str);}
   private:
      char* _str;
};

void f(const char*);

void g()
{
   String a = "Stuff ";
   String b = "Junk";
   // in the following, operator+ creates a temporary String, T1
   // then operator const char* creates a temporary const char* T2
   // is the compiler allowed to delete T1 before calling f()?
   f(a + b);

   const char* s = a + b;
   // it seems even more likely that T1 will be deleted before calling f()
   f(s);
}

Andy Jewell
avjewe@kaizen.net
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Pete Becker <petebecker@acm.org>
Date: 1997/07/26
Raw View
Andrew D Jewell wrote:
 >
 > I have a subtle question about the lifetime of temporaries.
 > As you see in the class String below, the result of
 > operator const char* becomes invalid after the String is destroyed.
 > I can't quite tell from the CD2 spec if either of my two examples
 > are guarenteed to be OK.
 >
 > 12.2.3 states that temporaries aren't destroyed until the end of the
 > "full expression".
 >
 > 1.8.13 states that a "full expression" is an expression that is
 > not a sub expression of another expression.
 >
 > My best guess is that my first example is OK, but my second
 > example is not.
 >
 > Can anyone confirm or deny this?
 >
 > class String
 > {
 >    public:
 >       String(const char* s) {_str = strdup(s);}
 >       operator const char*() const {return _str;}
 >       friend String operator+(const String& left, const String&
 > right);
 >       ~String() {free(_str);}
 >    private:
 >       char* _str;
 > };
 >
 > void f(const char*);
 >
 > void g()
 > {
 >    String a = "Stuff ";
 >    String b = "Junk";
 >    // in the following, operator+ creates a temporary String, T1
 >    // then operator const char* creates a temporary const char* T2
 >    // is the compiler allowed to delete T1 before calling f()?
 >    f(a + b);
 >
 >    const char* s = a + b;
 >    // it seems even more likely that T1 will be deleted before calling
 > f()
 >    f(s);
 > }
 >

Yup, that's trouble. And that's one of the major reasons why the
standard string class does not have an implicit conversion to char *.
 -- Pete
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: "Paul D. DeRocco" <pderocco@ix.netcom.crud.com>
Date: 1997/07/28
Raw View
Andrew D Jewell wrote:

> void g()
> {
>    String a = "Stuff ";
>    String b = "Junk";
>    // in the following, operator+ creates a temporary String, T1
>    // then operator const char* creates a temporary const char* T2
>    // is the compiler allowed to delete T1 before calling f()?
>    f(a + b);
>
>    const char* s = a + b;
>    // it seems even more likely that T1 will be deleted before calling f()
>    f(s);
> }

Yup, s will be pointing to deallocated memory by the time f is called.
If you make s a String, then the temporary will be copied into a more
permanent string (or perhaps a+b will be constructed into that more
permanent string, if the compiler's really clever), and then operator
const char* will do the necessary conversion in the call to f.

--

Ciao,
Paul

(Please remove the extra "crud" from the return address,
which has been altered to foil junk mail senders.)
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: sdm@cs.brown.edu (Scott Meyers)
Date: 20 Sep 91 20:15:44 GMT
Raw View
I posted this to comp.lang.c++, but nobody bit.  I thought I'd give it a
try here.

In article <288@uim.UUCP> roger@procase.uucp (Roger H. Scott) writes:
| struct s {
|     int m;
|     const int& getM() {return m;}
| };
|
| extern s f();
|
| const int&
| g() {
|     return f().getM();
| }
|
| Do you see the problem here?

Actually, yes.  The return value of f is a temp, so g is returning a
reference to part of a temporary object.  Not a good idea.

ARM 12.2 discusses the lifetime of temporaries, but I've never been able to
understand it.  All you can do to a temp, it sez, is fetch it or bind a
reference to it.  Well, if we call the temp returned by f TEMP, then what
are we doing to TEMP when we invoke TEMP.getM?  Are we fetching its value
or binding a reference to it, or am I totally confused?  In particular,
when is the earliest that a valid C++ compiler is allowed to destroy TEMP?

    - after f returns but prior to calling getM?
    - after calling getM but before returning?
    - after getM returns but before g does?
    - only after g returns?

Scott

-------------------------------------------------------------------------------
What do you say to a convicted felon in Providence?  "Hello, Mr. Mayor."