牛客网——const二级指针报错: 无法从“int **”转换为“const int **”

1 篇文章 0 订阅

喵哥在牛客网遇到这么一题选择题:

class A { };
void f(const A** p) {} 
void g(const A * const *p) {}
void k(const A*&p) {}

int main()
{
	const A * ca = new A();
	A*a = new A(); 
	A** p = &a; 
	k(ca);   //1
	f(p);  //2
	g(p);//3
    return 0;
}

大概要选的选项是1,2,3语句正确与否的组合,正确答案是1,3正确,2错误。

这是一道关于const对象赋值的判断,扯远一点:

const包含顶层const和底层const。顶层const表示对象本身是常量,而底层const表示对象指向的对象是一个常量。通常顶层const对任何数据类型都适用,但是底层const只包含指针和引用,其中引用const必定是底层const。

顶层const的复制比较宽松,而底层const必须注意一些要点:在执行拷贝时,拷入和拷出的对象必须具有相同的底层const资格,或者两个对象的数据类型可以互相转换。一般的,非常量对象可以转为常量(针对底层const)。

回到题中。

语句1中用到的k函数的参数是const A*&p,这是一个指向A类型常量的指针的引用,引用在此处的作用是可以传值。ca的类型正好是指向A类型常量的指针,正确。

语句2中用到的f函数的参数是const A** p,是一个指向A类型常量的二级指针(指向指向A类型常量的指针的指针)。p的类型是指向A类型的二级指针。根据前文所述:“一般的,非常量对象可以转为常量”,这样的赋值似乎是合理的,但是这里面存在一个毁灭性的缺陷,如下:

int main()
{


	const int x = 1;
	int* p;
	const int** q = &p;  //假设int**可以赋值到const int **
	*q = &x;             //现在将q指向的指针赋为常量x的地址(*q即为指针p的地址,这时p指向x)                       
	*p = 2;               //由于p是非常量的,所以对其赋值很正常,但是这样就修改了常量x的值!!!
	printf("%d", x);
    return 0;
}

可见,如果int**可以赋值到const int**会导致某些常量被“合情合理”地修改了,这跟常量的定义相违背。那么如何才能使得二级指针的非常量转换到常量呢?分析代码,发现只要*q = &x不成立即可,那么保证*q为常量。

const int*const* q = &p;

如此书写便可以保证不出错。事实上,这是C语言中遗留的缺陷,C++将其修复:禁止int**复制到const int** ,但是允许int**复制到const int*const*。从而语句3正确。

 

 

 

 

 

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值