T** 不能隐式转换成 const T** 的原因

来源:互联网 发布:vb常用代码 编辑:程序博客网 时间:2024/06/12 03:44

我们用T来表示类型,这里的类型可以是系统内置类型,也可以是用户自定义类型。

首先要明确一点:将T** 类型的指针赋给 const T**类型的指针是不合法的,即使你非要强制转换来赋值,那样做也是十分危险的。

大家都知道,C++允许我们将T*类型的指针赋值给const T*类型的指针,这是因为const T*类型的指针具有底层const属性,它可以保证通过它,你不能修改它指向的内容。

但是,到指针升级为二维指针,情况就变了。虽然,从直觉上来讲,应该可以赋值。但在这里,直觉是错误的。

首先,我们先弄清两个概念:

char** 表示: pointer to pointer to char.

const char** 表示: pointer to pointer to const char.

const T c;const T* p;const T** myPtr;myPtr = &p;p = &c;

对于上述代码,在内存中,指针是这样分布的:


红色部分正是薄弱环节处。这是由const T** myPtr; 这样的定义引起的。对于myPtr来说,在语法层面,指针(*myPtr)是可以指向const T变量的。这正是薄弱环节所在。

看下面这个程序:

const char c = 'c';char* p;const char** myPtr = &p; // #1: not allowed*myPtr = &c;*p = 'C'; // #2: modifies a const object

通过上图我们也可以看到,因为(*myPtr)可以指向const char c,如果允许T** 赋值给 const T**,即允许myPtr指向普通指针p,则之后我们让指针p以(*myPtr)的名义再指向const变量c,那么我们就可以通过指针p来修改 c 的值了。

所以不允许T** 赋值给 const T**,也就是说,不允许T** 类型的指针隐式转换成 const T**。

T** → const T** 要被禁止,是因为这样做可能会在无意中改变一个const常量的值

那怎么解决T** 向 const T**赋值的问题呢?

我们再来看一个例子:

class Foo { /* ... */ };void f(const Foo** p);void g(const Foo* const* p);int main(){  Foo** p = /*...*/;  // ...  f(p);  // ERROR: it's illegal and immoral to convert Foo** to const Foo**  g(p);  // Okay: it's legal and moral to convert Foo** to const Foo* const*  // ...}

看过上面的例子,我们就可以很清楚怎么解决这个问题了。

即将const char** myPtr; 修改为 const char* const* myPtr;

当然,对于char** 类型的指针,可以隐式转换成 char * const * ,也可以转换成const char * const * .

0 0