Literal initialization for const references
How does the following code work in C++? Is it logical?
const int &ref = 9;
const int &another_ref = ref + 6;
Why does C++ allow literal initialization for const references when the same is not permitted for non-const references? E.g.:
const int days_of_week = 7;
int &dof = days_of_week; //error: non const reference to a const object
This can be explained by the fact that, a non-const reference can be used to change the value of the variable it is referring to. Hence, C++ does not permit a non-const reference to a const variable.
Could this be a possible explanation? C++ does not allow:
int &ref = 7;
Because that is not logical, but:
const int &ref = 7;
Is almost equivalent to:
const int val = 7;
So literal initialization is permitted for const vari开发者_高级运维ables.
P.S.: I'm currently studying Lippman's C++ Primer.
So you can write code like this:
void f( const string & s ) {
}
f( "foobar" );
Although strictly speaking what is actually happening here is not the literal being bound to a const reference - instead a temprary string object is created:
string( "foobar" );
and this nameless string is bound to the reference.
Note that it is actually quite unusual to create non-parameter reference variables as you are doing - the main purpose of references is to serve as function parameters and return values.
Constant references can be initialized with literals and temporaries because you can trivially transform them to explicit variables:
int const& ans = 42;
// tranformed:
int __internal_unique_name = 42;
int const& ans = __internal_unique_name;
Or when the lifetime is not extended, such as a function parameter:
f("foobar");
// transformed:
{
string __internal_unique_name = "foobar";
f(__internal_unique_name);
}
(Notice the explicit block in this case.)
While it's possible to do something similar in the non-constant case, that's just not allowed in currenct C++. C++0x (the next standard), however, will have r-value references.
If it wasn't clear, ref + 6
from your code creates a temporary object, which you can visualize as:
int const& ref = int(9);
int const& another_ref = int(ref + 6);
// transformed:
int __A = 9;
int const& ref = __A;
int __B = ref + 6;
int const& another_ref = __B;
This may help you understand/visualize what is happening, but you should not write real code like this. Also I've used double underscore names to illustrate those names are implementation details (used by the compiler) and should not be used by you. Any name which contains adjacent underscores is reserved to the C++ implementation.
Your code boils down to the C++ standard rule where the lifetime of a temporary value is bound to the lifetime of the const
reference to which it is assigned. See the GoTW article GotW #88: A Candidate For the “Most Important const” for additional details.
For example, the ScopeGuard
implementation, described by Alexandrescu and Marginean in the Dr. Dobbs article "Generic: Change the Way You Write Exception-Safe Code — Forever" depends on this behavior.
精彩评论