[comp.lang.c++] lifetime of temporary objects

kearns@read.columbia.edu (Steve Kearns) (06/25/89)

On pg. 43 of the "bible" it says:
"an object is created when its definition is encountered and 
 destroyed when its name goes out of scope."

What about temporary variables:  for example,
with the following declarations...

struct foo {int * dummy...};
foo foo::make();
int bar(int);

... is the lifetime of the temporary "foo" returned by foo (below)
guaranteed not to be destructed until after bar returns?  

bar(make().dummy);

This can be important when doing reference counting.
The above code is more efficient than the alternative:

// define bar to take a ref instead
int bar(foo& )
// call bar this way
bar(make());

-steve
(kearns@cs.columbia.edu)

ark@alice.UUCP (Andrew Koenig) (06/25/89)

In article <6374@columbia.edu>, kearns@read.columbia.edu (Steve Kearns) writes:

> On pg. 43 of the "bible" it says:
> "an object is created when its definition is encountered and 
>  destroyed when its name goes out of scope."

> What about temporary variables:  for example,
> with the following declarations...

> struct foo {int * dummy...};
> foo foo::make();
> int bar(int);

> ... is the lifetime of the temporary "foo" returned by foo (below)
> guaranteed not to be destructed until after bar returns?  

> bar(make().dummy);

First of all, this example contains an error: bar takes an int
argument, but foo::dummy is an int*.  Moreover, the call to make()
requires an object, unless the call to bar is textually inside a
member function of foo.

That said, here's a similar example:

	class Foo {
	public:
		int a;
		Foo();
		~Foo();
	};

	Foo f();
	void bar(int);

Given these declarations, what about

	bar(f().a);

The answer is that once element `a' has been extracted from
the value returned by f(), that value is no longer needed and
can be destroyed.  However, it is not required to be destroyed
until the end of the block that allocated the temporary.

Thus, a C++ implementation is free to do this:

	int temp = f().a;
	bar(temp);

and it may destroy the temporary containing the result of f()
either before or after the call to bar.

Here's another closely related example:

	void baz(Foo&);

	baz(f());

Here, a reference is bound to the temporary containing the result
of f() so it can be passed to baz.  When a reference is bound to
a temporary, the temporary is not destroyed until sometime after
the reference is destroyed.  Thus this particular temporary must
remain at least until after baz() has returned.  Similarly:

	Foo& r = f();

The reference `r' has been bound to the temporary containing the
result of f; that temporary must therefore persist until the end
of the block containing this declaration.

I have written several classes that do reference counting; part
of the effect of these rules is to make such classes work sensibly
without much difficulty.
-- 
				--Andrew Koenig
				  ark@europa.att.com