Here is the code:
int main()
{
int* p = nullptr;
const int* cp = p;
const int*& ref = cp;
const int*& ref0 = cp;
const int*& ref1 = p;//not allowed
const int*& ref2 = static_cast<const int*&>(p);//not allowed
int* const & ref3 = p;//allowed. Why?
return 0;
}
When I run it, I got
test.cpp:7:14: error: non-const lvalue reference to type 'const int *' cannot
bind to a value of unrelated type 'int *'
const int*& ref1 = p;
^ ~
test.cpp:8:21: error: non-const lvalue reference to type 'const int *' cannot
bind to a value of unrelated type 'int *'
const int*& ref2 = static_cast<const int*&>(p);
I am having trouble understanding why. Maybe const
plays a role here. And when I wrote const int*&
or int* const &
, I don't know const
apply to pointer or reference. And const int* const &
confuses me too. I want to know the syntax for the following item:
A reference to a pointer that is const.
A reference to a pointer that points to a const.
A reference to a pointer that is const and points to a const.
And const reference version:
A const reference to a pointer.
A const reference to a pointer that is const.
A const reference to a pointer that points to a const.
A const reference to a pointer that is const and points to a const.
Sorry for my confusion.
Your p
is a pointer to an int
. const int*&
is a reference to a pointer to a const
int
. Since p
is an int
and not a const
int
, you cannot bind a reference that is supposed to refer to a pointer to a const
int
to refer to p
.
The key to reading declarations in C++ is to read them "from the inside out", ie, start from the identifier (name) and work your way out. Take your example:
int* const & ref3;
is a reference to a const
pointer to an int
. We start at the identifier ( ref3
) and work outwards. The first thing we find is an &
. So ref3
is a reference. Next thing is const
, so whatever ref3
refers to is a const
something. Next thing is a *
, so the const
thing the reference refers to is a pointer. Finally int
, we're dealing with a reference to a const
pointer to an int
.
Note that you can have stuff happening to both sides of the identifier. When "working your way out", you have to consider which specifiers/operators bind first/more strongly to figure out what type is declared. For example:
int const * a[10];
Again, we start at the identifier a
. The []
binds more strongly than *
, so a
is an array of 10 elements. What are these elements that a
is an array of? Next comes a *
, so a
is an array of 10 pointers to something. In the end, we find that a
is an array of 10 pointers to const
int
. Note that if there's a lonely const
left at the end, that const
binds to whatever came before it. That's what allows us to also write const int a
which is equivalent to int const a
.
You can also use parentheses to influence the order in which operators take effect in a declaration. For example
int const (* a)[10];
would be a pointer to an array of 10 const
int
rather than an array of 10 pointers to const
int
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.