首页 > 试题广场 >

如下代码段,哪种描述是正确的()

[单选题]

如下代码段,哪种描述是正确的()

#include <iostream>
using namespace std;
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;
}



  • 全部正确
  • 2错,1,3正确
  • 1,2错,3正确
  • 1正确,2,3,错
变量声明的类型与初始化值无关
发表于 2018-09-18 21:18:30 回复(0)
更多回答
求个大佬讲解一下,怎么没看懂。。。为啥3是对的
发表于 2018-05-16 09:48:30 回复(0)
哪位大神可以解释下 3呢?
发表于 2017-08-06 08:41:28 回复(2)
C++规定不能将A** 转换为const A**(在C语言中是可以的,这个缺陷被C++修正)
我们看看假如允许这种转换,将会发生什么错误
参考代码:
int main()  
{  
    const int x = 1;  
    int* p;  
    int const** q = &p;  //① q为一个指向const int*的指针,现在将其指向non-const int*  p  
    *q = &x;             // ②现在将q指向的指针赋为常量x的地址(*q即为指针p的地址,这时p指向x)
    //**q=2;             //③报错
    *p = 2;               //④因为p是non-const int *,所以可以对其赋值,这时将常量x的值改为了2,明显不符合常识
    printf("%d",x);
}  
这里的关键在于引入了中间指针p,虽然q本身被const **限制,使得*q是const* ,从而**q不能被修改(见代码④),但是(*q)如果可以是non const*的话(如我们熟悉的const int*可以被赋值为int* ),p=*q是指向non-const的,可以被修改,显然不合理。

而选项3正确的原因在于参数 const A* const*q,说明p指向一个const 指针(*q),这个const 指针再指向const对象。 const 指针本身不能被修改,所以上面代码②会 报错。即q指向A**也无影响。

参考  http://blog.csdn.net/duyiwuer2009/article/details/39401801

发表于 2017-01-04 23:28:05 回复(4)

仅仅总结如下:

1.const A *等价 A const *。

2.允许用A *赋值A const *。

3.允许用A**赋值A const*const *。即选项③

4.不允许用A**赋值A const**。即选项②。


允许用非常量赋值底层const,在看primer的时候也不是很懂,有大神讲讲吗?也就是上边第2个,只知道是规定,这样规定的原因是?

编辑于 2019-09-17 22:59:27 回复(1)
规律在于将一个A***...*** 这样的一级以上的复合指针类型赋予指针p,如果不使用原型声明,那么p必须保证是A…const*p。也就是说p必须指向一个常量,否则就会产生中间指针遭到篡改的风险。所以题目中也一样,对于.[3]选项的函数形参,改为A*const*p也是可以的。只要保证p不能改变其指向的内存单元所存储的内容即可。一旦你选择放弃这枚关键const,那就必须将剩余的间接指针全都使用一致的声明。
编辑于 2017-08-29 04:28:16 回复(1)
这个怎么理解呢?
其实,在C++ primer中有说道,为了使函数的形参能够接受不同版本的参数(const和非const版本),我们可以都定义为const版本;也就是说:非const可向const转型,反之则不然;以上回顾了一下基础知识;
看这道题,这道题的问题出在了二级指针上面;那我来具体说说吧:
变量(包括指针变量)const转型都不会出问题;以下是基本的底层指针和顶层指针(添加了const特性):

在底层或者顶层const上继续添加仍然不会有问题:
继续在其上添加,仍然不会就出问题:

也许我们已经发现了,分别就底层或者顶层const增加指针等级,是不会有问题的;
来看看这个题吧,关键在于指针a指向的对象A是非const的;而且使用了二级指针;记住:指向底层const的指针只是自己(指针自己)保证不会去修改所指向的内容;这里,对于f函数,p做出保证:不会去修改底层const变量的值,但是p指向的是一个指针(比如说q)啊,q指针是个非const指针,它可以随心所欲地改变变量,此时,如果变量是const的话,就出错了:

(const)表示可有可无,有没有都是错的,因为编译器阻止你这么做。
但是,如果一级指针也做出这样的保证,那就正确了;

换一种形式表达就是:

二级指针同时保证了一级指针也固定,不乱修改人家的值;
好了,下面给出几种正确的形参类型:

编辑于 2020-05-07 13:24:02 回复(0)
const放在类型前意在表明无法修改类型实例,如果允许将A**转换为const A**,那么const毫无意义,因为大可以通过A**指向另一个A*来修改这个A的实例,C++不允许你搞这种蠢事和无聊的逻辑。而A**转换为const A *const*则使得“无法修改类型实例”的初衷得以实现,“大可以通过A**指向另一个A*来修改这个A的实例”的现象也被堵死,C++允许你这么表达。至于const A*&表达的是一个const A*指针的引用,而不是const *指针的引用.
语言是种规范,逻辑要自洽,不自洽要么被堵漏,要么被舍弃。
编辑于 2020-08-25 22:43:00 回复(0)
const A **p只保证了自己不修改底层的值,但没有保证*p不修改底层的值,这样*p能修改底层的值而**p却又禁止修改,显然是不符合逻辑的
如果要用const修饰的话,就必须对每一层指针都做出保证,如const A *const *p;
注释:
1)在c++中const A * 等价于A const *
2)在A**中,前一个*代表二级,后一个*代表一级
发表于 2020-08-06 12:44:48 回复(0)
C++ 中,A**不能转换为constA **

举个栗子:
const int val = 0; // 定义const int类型对象
int *ptr = nullptr; // 合法

const int  **p = &ptr; // 非法,要求 int** -> int const**
//假设合法,则 *p = &val 合法,等价于 ptr = &val
//这使得通过非 const 限定指针修改 const 对象而无需 const_



发表于 2020-04-19 22:34:28 回复(0)
关于const int * &p; 

int * &p=a; 

把 int * 看成一个类型,a就是一个整型指针,p 是a的别名。


发表于 2020-03-19 15:59:00 回复(0)
说白了要一层const下面层都要const 以免中间层修改
发表于 2019-06-04 19:40:51 回复(0)
看的有点头皮发麻,这指针真的让人头晕
发表于 2019-05-21 22:35:28 回复(0)
我咋觉得都对的呢……
发表于 2017-01-04 19:02:19 回复(2)
int *p表示的是一级指针,表示p所指向的地址里面存放的是一个int类型的值。
int **p表示的是二级指针,表示p所指向的地址里面存放的是一个指向int类型的指针。
一级指针存放变量的地址,指向的值是变量的内容。如int* p={1,2,3}, p=数组的首地址,*p=数组的第一个值;
二级指针存放一级指针的地址,指向一级指针。如int*p ={1,2,3}, int**pp=&p,pp=指针p的首地址,*pp=数组的首地址,**pp=数组第一个值1。
编辑于 2020-02-27 16:34:12 回复(0)
class A{};
void f(const A** p){}
int main(int argc, char **argv){
    int scalara = 0, *pointa = 0;
    int *pointer_to_var = &scalara;
    int ** pointer_to_pointer_to_scalar = &pointa;
    const int ** pointera_to_pointer_to_const = pointer_to_pointer_to_scalar;
    int ** pointer_to_pointer_to_var = &pointer_to_var;
    const int ** pointerb_to_pointer_to_const = pointer_to_pointer_to_var;
    
    A *a = new A();
    A ** pointer_to_pointer_to_class = &a;
    const A** pointer_to_pointer_to_constclass = pointer_to_pointer_to_class;
    f(pointer_to_pointer_to_class);
    const A *b = new A();
    f(&b);
}

编译环境是:

编译器是允许的,如果编译选项中不包含“-fpermissive”则会报错


编辑于 2022-12-08 15:35:03 回复(0)
2的形参是const A** p,实参是 A** p。假设可以隐式转化,那么由形参可知**p是const,不能修改。但由于实参是A** p,所以可以通过改变*p的指向使得**p被修改,假设不成立。所以形参应该为const A* const* p。
发表于 2022-10-13 16:55:56 回复(0)

头皮发麻

发表于 2019-12-04 16:20:30 回复(0)
error: invalid conversion from 'A**' to 'const A**',故2错,选B。
编辑于 2018-11-24 19:52:46 回复(0)
1中p是对指针ca的引用

发表于 2018-09-11 21:31:08 回复(0)