By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,260 Members | 1,338 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,260 IT Pros & Developers. It's quick & easy.

Object lifetimes when bound to references

P: n/a
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 location in memory?

Examples:

int f1()
{
int a=1;
return a;
}

int& f1r() // note that the return type changed
{
int a=1;
return a;
}

int f2()
{
int a(1),b(2);
return a+b;
}

int& f2r()
{
int a(1),b(2);
return a+b;
}

....
/* 1 */ const int& ref = f1();
/* 2 */ const int& ref = f1r();
/* 3 */ const int& ref = f2();
/* 4 */ const int& ref = f2r();
/* 5-8 */ <like 1-4 but without const qualifier>

Can you comment expressions 1-8 regarding their behavior (defined,
undefined) and the lifetime of the objects which are aliased?

Thanks a lot.

--
Matthias Kaeppler
Jul 23 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a
Matthias Kaeppler wrote:
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.
That only refers to a temporary bound _directly_ to a const reference.
But does it e.g. matter if the temporary was created in scope of a
function body and has to outlive the function call?
In a normal execution of the program, a temporary created in the body
of a function cannot outlive the function call. The only way where
a temporary created inside a function can outlive the function by
having a reference bound to it is when an exception is thrown.
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 location in
memory?
That's unspecified, IIRC.

Examples:

int f1()
{
int a=1;
return a;
}

int& f1r() // note that the return type changed
{
int a=1;
return a;
Undefined behaviour. You're returning a reference to a local variable.
As soon as the function returns, the reference is invalid.
}

int f2()
{
int a(1),b(2);
return a+b;
}

int& f2r()
{
int a(1),b(2);
return a+b;
Ill-formed. A reference to a non-const object is [attempted to be] bound
to a temporary. Shall not compile (8.5.3/5).
}

...
/* 1 */ const int& ref = f1();
/* 2 */ const int& ref = f1r();
/* 3 */ const int& ref = f2();
/* 4 */ const int& ref = f2r();
/* 5-8 */ <like 1-4 but without const qualifier>

Can you comment expressions 1-8 regarding their behavior (defined,
undefined) and the lifetime of the objects which are aliased?


Cases 1 and 3 have const references bound to temporaries created as
the result of functions returning an object. Those objects live as long
as the references live (in the surrounding scope, which can be as broad
as global). The temporaries are not actually created *inside* the
function.

All other cases either have undefined behavioir because you're returning
a reference to a local object or ill-formed because a non-const reference
cannot be bound to a temporary object.

V
Jul 23 '05 #2

P: n/a
Victor Bazarov wrote:
Matthias Kaeppler wrote:
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.

That only refers to a temporary bound _directly_ to a const reference.


Do you have the paragaph at hand which backs this statement?

--
Matthias Kaeppler
Jul 23 '05 #3

P: n/a
Victor Bazarov wrote:
Matthias Kaeppler wrote:
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.

That only refers to a temporary bound _directly_ to a const reference.

But does it e.g. matter if the temporary was created in scope of a
function body and has to outlive the function call?

In a normal execution of the program, a temporary created in the body
of a function cannot outlive the function call. The only way where
a temporary created inside a function can outlive the function by
having a reference bound to it is when an exception is thrown.

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 location in
memory?

That's unspecified, IIRC.

Examples:

int f1()
{
int a=1;
return a;
}

int& f1r() // note that the return type changed
{
int a=1;
return a;

Undefined behaviour. You're returning a reference to a local variable.
As soon as the function returns, the reference is invalid.

}

int f2()
{
int a(1),b(2);
return a+b;
}

int& f2r()
{
int a(1),b(2);
return a+b;

Ill-formed. A reference to a non-const object is [attempted to be] bound
to a temporary. Shall not compile (8.5.3/5).

}

...
/* 1 */ const int& ref = f1();
/* 2 */ const int& ref = f1r();
/* 3 */ const int& ref = f2();
/* 4 */ const int& ref = f2r();
/* 5-8 */ <like 1-4 but without const qualifier>

Can you comment expressions 1-8 regarding their behavior (defined,
undefined) and the lifetime of the objects which are aliased?

Cases 1 and 3 have const references bound to temporaries created as
the result of functions returning an object. Those objects live as long
as the references live (in the surrounding scope, which can be as broad
as global). The temporaries are not actually created *inside* the
function.

All other cases either have undefined behavioir because you're returning
a reference to a local object or ill-formed because a non-const reference
cannot be bound to a temporary object.

V


Alright, and what if I change the signature of f1r() to

const int& f1r()

and the signature of f2r() to

const int& f2r()

respectively?
--
Matthias Kaeppler
Jul 23 '05 #4

P: n/a
Matthias Kaeppler wrote:
Victor Bazarov wrote:
Matthias Kaeppler wrote:
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.

That only refers to a temporary bound _directly_ to a const
reference.


Do you have the paragaph at hand which backs this statement?


12.2/5, I believe.

The point of my statement is to say that

const int & i = 5;
const int & j = i;

does not make the temporary '5' persist as long as 'j' lives, only as
long as 'i' lives. IOW, the second initialisation is not "binding of
a temporary to a reference".

V
Jul 23 '05 #5

P: n/a
Matthias Kaeppler wrote:
Victor Bazarov wrote:
Matthias Kaeppler wrote:
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.

That only refers to a temporary bound _directly_ to a const
reference.
But does it e.g. matter if the temporary was created in scope of a
function body and has to outlive the function call?

In a normal execution of the program, a temporary created in the body
of a function cannot outlive the function call. The only way where
a temporary created inside a function can outlive the function by
having a reference bound to it is when an exception is thrown.

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 location in
memory?

That's unspecified, IIRC.

Examples:

int f1()
{
int a=1;
return a;
}

int& f1r() // note that the return type changed
{
int a=1;
return a;

Undefined behaviour. You're returning a reference to a local
variable. As soon as the function returns, the reference is invalid.

}

int f2()
{
int a(1),b(2);
return a+b;
}

int& f2r()
{
int a(1),b(2);
return a+b;

Ill-formed. A reference to a non-const object is [attempted to be]
bound to a temporary. Shall not compile (8.5.3/5).

}

...
/* 1 */ const int& ref = f1();
/* 2 */ const int& ref = f1r();
/* 3 */ const int& ref = f2();
/* 4 */ const int& ref = f2r();
/* 5-8 */ <like 1-4 but without const qualifier>

Can you comment expressions 1-8 regarding their behavior (defined,
undefined) and the lifetime of the objects which are aliased?

Cases 1 and 3 have const references bound to temporaries created as
the result of functions returning an object. Those objects live as
long as the references live (in the surrounding scope, which can be
as broad as global). The temporaries are not actually created
*inside* the function.

All other cases either have undefined behavioir because you're
returning a reference to a local object or ill-formed because a
non-const reference cannot be bound to a temporary object.

V


Alright, and what if I change the signature of f1r() to

const int& f1r()

and the signature of f2r() to

const int& f2r()

respectively?

As soon as the function returns and the full expression that contains
that funciton call is evaluated, the temporary is going to be destroyed.
So, in f1r a temporary will be created but will only live long enough
to make it to the outside. A reference initialised from that reference
( /* 2 */ const int& ref = f1r(); ) is still going to be invalid (thus
the program has undefined behaviour). The same with case 4.

V
Jul 23 '05 #6

P: n/a
Matthias Kaeppler wrote:
[...]

Wanted to add that if you wrote

const int& f2r() { int a(1), b(2); return a+b; }

...

const int& ref = f2r() + 0;

you would have a valid and definedly-behaved program because
there would be another temporary created to which 'ref' is bound
and that temporary would persist as long as 'ref' lives.

V
Jul 23 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.