引用遇上const和指针

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hzh_0000/article/details/79587972

情况一

int a = 1;
int b = 2;
const int *c = &a;
const int*  &d = c;
const int* const &e = c;

d = &b;//正确
e = &b;//错误
*d = 3;//错误

int *f = &a;
int* &g = f;
int* const &h = f;

g = &b;//正确
h = &b;//错误
*g = 3;//正确

当const引用是引用的一个指针的时候,那么指针的值是不能通过这个引用来改变值的。而前面的const int *则表示 指针所指向的类容是不能改变的。

情况二

知乎看的

int a = 10;
int *b = &a;
const int* &p = b;//错误
const int* const &p = b;//正确

直接编译得到的错误信息是:

error: invalid initialization of non-const reference of type 'const int*&' from an rvalue of type 'const int*'

对于代码:

const int* &p = b;

左边定义了一个叫p的引用。如果你写成 int* const &p,那么p无疑是『指向int*的常引用』。但原来的写法,p实际上是一个『指向const int*的(非常)引用』。那么等号右边呢?本来b是个左值,但类型是int*而非const int*。根据C++标准,下列隐式转换是允许的:

  • 左值到右值转换:一个(非函数,非数组)的类型T的左值可以隐式转换成同类型的右值;
  • 限定性转换:一个T类型的右值指针可以通过隐式转换来添加 const 和/或 volatile 限定。显然,转换之后仍然是右值。回到原题。

b是个int*左值,因此不能直接使用第二条规则来把它变成一个const int*左值。因此,先通过第一条规则把它转化成了右值,再使用第二条规则转化为const int*。等价于:

int const * & p = static_cast<int const*>(b);

但此时:

  • 右值的属性是逃不掉了。
  • 既然是个右值,原本是可以用来初始化常引用的。但这里的const并没有被用来限定&,此处的引用只是一个非常引用。

基于以上两点,最终触发了『不能用一个const int*右值来初始化一个对const int*的非常引用』的错误。

右边是右值,当然不能被左值引用捕获。不过C++还有一个特别的规定,就是如果左边是T const &的话,可以隐式捕获一个右值并延长他的生命周期。于是你写:

int * const & p = b;
int const * const & p = b;

就没有问题。

猜你喜欢

转载自blog.csdn.net/hzh_0000/article/details/79587972
今日推荐