Lifetime of a function argument.

J

Jason Heyes

I am interested in the lifetime of a function argument in two cases. They
are:

1. void foo(Bar bar);

2. void foo(const Bar &bar);

In each case I call foo like so:

foo(Bar());

What is the lifetime of Bar() in each case? I suspect that Bar() exists for
the duration of foo(const Bar &) and does not exist at all during foo(Bar).
Is this correct?
 
V

Victor Bazarov

Jason Heyes said:
I am interested in the lifetime of a function argument in two cases. They
are:

1. void foo(Bar bar);

2. void foo(const Bar &bar);

In each case I call foo like so:

foo(Bar());

What is the lifetime of Bar() in each case? I suspect that Bar() exists
for the duration of foo(const Bar &) and does not exist at all during
foo(Bar). Is this correct?

In the first case the temporary Bar exists only long enough to initialise
the function argument (or there is no temporary whatsoever). The argument
itself exists until the function returns.

In the second case the temporary Bar exists for the duration of the function
call (i.e. until the function returns), IOW for the lifetime of the
reference
bound to that temporary.

V
 
J

Jonathan Mcdougall

Jason said:
I am interested in the lifetime of a function argument in two cases. They
are:

1. void foo(Bar bar);

2. void foo(const Bar &bar);

In each case I call foo like so:

foo(Bar());

What is the lifetime of Bar() in each case? I suspect that Bar() exists for
the duration of foo(const Bar &) and does not exist at all during foo(Bar).
Is this correct?

With no optimizations, for a call foo(Bar()),

1. void foo(Bar bar);
A "temporary" object is created and then the argument 'bar' is
copy-constructed with that object. That 'bar' objecy follows
normal C++ rules. The original object is destroyed at the end of
the function-call expression (basically at the closing parenthesis
of the function call).

2. void foo(const Bar &bar);
A "temporary" object is created and the argument 'bar' becomes a
reference to it. The reference follows the normal rules and the
original object behaves exactly as in #1.

With optimizations, the "temporary" Bar() will probably be eliminated
for the by-value argument.


Jonathan
 
V

Victor Bazarov

Jonathan Mcdougall said:
With no optimizations, for a call foo(Bar()),

1. void foo(Bar bar);
A "temporary" object is created and then the argument 'bar' is
copy-constructed with that object. That 'bar' objecy follows
normal C++ rules. The original object is destroyed at the end of
the function-call expression (basically at the closing parenthesis
of the function call).

I think you need to refresh your memory by reading 12.2/4. If the copying
takes place, the temporary dies before the function begins execution. If
the copy is eliminated, the argument inside the function is the only thing
that has a lifetime and it lives while the function executes.
2. void foo(const Bar &bar);
A "temporary" object is created and the argument 'bar' becomes a
reference to it. The reference follows the normal rules and the
original object behaves exactly as in #1.

With optimizations, the "temporary" Bar() will probably be eliminated for
the by-value argument.

V
 
J

Jonathan Mcdougall

Victor said:
I think you need to refresh your memory by reading 12.2/4. If the copying
takes place, the temporary dies before the function begins execution. If
the copy is eliminated, the argument inside the function is the only thing
that has a lifetime and it lives while the function executes.

I didn't know that, thanks.


Jonathan
 
M

Michiel Salters

Victor Bazarov said:
I think you need to refresh your memory by reading 12.2/4. If the copying
takes place, the temporary dies before the function begins execution. If
the copy is eliminated, the argument inside the function is the only thing
that has a lifetime and it lives while the function executes.

You could be partially right, but 12.2/4 says something else: "
There are two contexts in which temporaries are destroyed at a different
point than the end of the full expression. The first context is when a
default constructor is called to initialize an element of an array...
The second context is when a reference is bound to a temporary."

No array, no reference, so 12.2/4 does not apply. (There might have been
slightly different wording in C++98, are you perhaps using that?)

Regards,
Michiel Salters
 
V

Victor Bazarov

Michiel Salters said:
You could be partially right, but 12.2/4 says something else

What document are you quoting?
: "
There are two contexts in which temporaries are destroyed at a different
point than the end of the full expression. The first context is when a
default constructor is called to initialize an element of an array...
The second context is when a reference is bound to a temporary."

No array, no reference, so 12.2/4 does not apply. (There might have been
slightly different wording in C++98, are you perhaps using that?)

Yes, in 1998 edition 12.2/4 starts with "There are two contexts in which
temporaries are destroyed at a different point than the end of the
full-expression. The first context is when an expression appears as
an initializer for a declarator defining an object. In that context,
the temporary that holds the result of the expression shall persist
until the object's initialization is complete."

V
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,160
Latest member
CollinStri
Top