C++中指针与Const

众所周知,C++中指针是C++强大力量的来源之一,也是比较容易让初学者迷惑的地方,如果再加上const修饰符,可能大家就更感觉头晕了,const放在*的前面和放在后面的区别是什么,在函数参数传值的时候,哪种const需要我们注意?在函数重载的时候,哪种const又会被认为是不同的函数参数?让我们简单来看看吧。
 

Const在指针的不同位置

首先让我们来看看Const在不同的位置下面对指针的影响。

int * ip1 //只能指向一个unconst int
const int * ip2;  //可以指向一个const int 或unconst int
int * const ip3;  //const 修饰指针,该指针不能再指向其他对象
const int * const ip4; //该指针不能指向其他对象,同时可以指向const int

从上面我们可以看出,const在指针里面的位置很大程度上面决定了指针的含义,在阅读const的时候从右到左阅读,*后面的部分修饰指针本身,前面的部分修饰想要指向的对象。
 

Top-Level和Low-Level

从上面我们知道,const可以修饰所指的对象,也可以修饰指针本身。请注意,

  • 当修饰所指对象的时候,该指针具有了指向const对象的能力(但是同时指向非const对象也是完全可以的,只是这个指针认为自己指向了一个const对象),但是通过这个指针修改这个对象是非法的,毕竟指针认为自己指向的是一个const对象(虽然有可能实际上不是),这时const修饰所指向的对象,也叫Low-Level const。
int i = 10;
const int *ip = &i;
*ip = 20; //error
  • 从另一个方面来说,当const修饰指针的时候,该指针不能再指向其他对象(const限定了指针只能指向这个对象不能改变),但是通过指针修改这个对象的值是被允许的(如果没有Low-Level const的话),这时const修饰指针自己,也叫Top-Level const。
int i = 10;
int j = 20;
int * const ip = &i;
*ip = 0; //valid
ip = &j; //error

总而言之一句话,如果const修饰的是指针本身,就叫Top-Level const,如果仅仅修饰被指向的对象,那么叫Low-Level const。
 

Top-Level和Low-Level在当函数参数时的不同表现

Top-Level和Low-Level在充当函数参数的时候尤其需要引起我们的关注。

  • Top-Level const 在充当函数参数的时候,const被忽略。
    什么意思呢?就是说当函数重载的时候,如果参数仅仅在const上面有区别,那么这个区别是会被编译器忽略的,举个例子。
void Test(int * ip)
{
}

void Test(int * const ip) //已经有主体,错误
{
}

理解这一点的关键是知道C++里面的参数默认使用值传递,传递到函数体里面的,是原来的指针的一个拷贝,而拷贝的时候,Top-Level const会被忽略从而产生出一个unconst的指针。所以在函数声明中,Top-Level const会被编译器忽略。

  • Low-Level const 在函数声明中不会被忽略
    另一方面,Low-Level const指针在函数声明中不会被忽略,因为Low-Level const 修饰所指向的对象,可以把有没有Low-Level const修饰符的指针,看作两个不同的数据类型。

void Test(int const * ip)
{

}

void Test(int * ip) //编译成功
{

}
  • 最后补充一下,可能有很多朋友会觉得,要是使用传引用的方式,传递Top-Level const指针进函数,这时函数内部可能改变这个指针(没有copy保护),那么编译器会忽略这个Top-Level const修饰符吗?
void Test(int * const & ip)
{

}

void Test(int * & ip)  //valid
{

}

这段代码是没问题的,编译器早考虑到了这个问题,所有reference的const,都是Low-Level const,所以编译器会认为这两个是不同的函数。

猜你喜欢

转载自blog.csdn.net/deatharthas/article/details/89293464
今日推荐