常量指针错误

3

我正在学习常量指针,尝试着使用以下内容:

#include<iostream>
using namespace std ;
int main(){
    int a = 10 ; 
    const int *cp  = &a ;               // my constant pointer variable
    cout<<"\nAddress stored in cp = "<<cp ;
    ++cp;
    cout<<"\nAddress stored in cp = "<<cp   ;
}

它增加了存储在cp中的地址。但是根据我现在理解的情况,++cp不应该出错,因为它是一个常量指针,始终指向同一地址,这个地址不能被修改。
但是当我用以下代码替换 const int *cp = &a ;int *const cp = &a ; 它给我这个结果 enter image description here 请原谅我的无知,难道它们不应该意味着相同的事情吗?

http://c-faq.com/decl/spiral.anderson.html - chris
1
个人而言,我不喜欢阅读类型时采用“螺旋式”方法。我建议您将 const 放在正确的位置,即在类型被声明为 const 时,将其放在类型的右侧而非左侧,如上述代码中的 int const *int * const。然后从右向左阅读。 - David Rodríguez - dribeas
@chris:螺旋规则是错误的。请听David Rodriguez的意见。 - kotlomoy
@kotlomoy,螺旋规则在读取类型时从未让我失望过。唯一的例外是这个Cv限定符允许放在左边。如果我能重新命名它,我会更喜欢叫做交替右-左规则,但一旦你了解了这个技巧,你很难找到无法阅读的类型。 - chris
@chris:“你很难找到你无法阅读的东西。” - int a [2] [3]。附注:我根本没有受到压力。 - kotlomoy
5个回答

2
当你执行 int *const cp = &a; 时,它意味着一个整数指针指向一个常量cp,因此cp不能改变。然而,在你之前的版本中,const int *cp 意味着一个指向常量的整数指针cp,所以cp指向的值不能改变,但指针本身可以。

通常,人们喜欢从右到左阅读这个:

const int *cp cp是一个指向整数常量的指针,因此整数值不能改变。 int *const cp = &a; cp是一个指向整数的常量指针,因此指针不能改变。

2
const int *cp  = &a ; 

cp指向的地址内容是只读的,但是指针cp本身不是只读的。

因此,

*cp = value ; //Illegal
++cp ; // Legal

int *const cp = &a ;

指针是只读的,但是由cp指向的地址中的内容是可读写的。

因此,

*cp = value ; //Legal
++cp ; // Illegal

此外,
const int *const cp  = &a ;

指针 cp 所指的地址和内容都是只读的

*cp = value ; //Illegal
++cp ; // Illegal

简单声明的话,需要从右往左读。

1
const int *cp1  = &a ; // pointer is variable, pointed to is constant
int *const cp2  = &a ; // pointer is constant, pointed to is variable
const int *const cp3  = &a ; // pointer is constant, pointed to is constant

因此,
cp1++; // possible
*cp1++; // not possible
cp2++; // not possible
*cp2++; // possible
cp3++; // not possible
*cp3++; // not possible

1
如果有帮助的话(可能并没有),以下是同义的,利用了语言的一个小技巧,允许开放类型在类型的立即左侧或右侧出现const,但在任何其他限定符之前(如指针或引用)。
const int * p; // does NOT require initialization
int const * q; // same as above

两者都声明指向常量int数据的指针,并且在语法上可以互换。

然而这段代码:

int * const p = &a; // requires initialization.

声明一个指向 int 数据的常量指针;不是 指向常量 int 数据的指针。
进一步扩展(实际上是将它们合并),我们得到:
const int * const p = &a;
int const * const p = &a;

这两个词是同义词。它们都声明了一个指向常量整数数据的常量指针。指针和指向的内容都不可修改,并且都需要初始化。

无耻地复制的图表

以下内容是从我自己(好吧,并不那么丢脸)和一个稍微相关的问题中无耻地复制而来。我希望它能更好地解释当您在声明中放置const*时会发生什么不同:

单重间接寻址

char *p;               // p is mutable, *p is mutable
const char *p;         // p is mutable, *p is const
char const *p;         // same as above.
char *const p;         // p is const, *p is mutable, must be initialized.
char const *const p;   // p is const, *p is const, must be initialized.

双重间接引用:
char **p;        // ptr-to-ptr-to-char
                 // p, *p, and **p are ALL mutable

const char **p;  // ptr-to-ptr-to-const-char
                 // p and *p are mutable, **p is const

char const **p;  // same as above

char *const *p;  // ptr-to-const-ptr-to-char
                 // p is mutable, *p is const, **p is mutable.

char **const p;  // const-ptr-to-ptr-to-char
                 // p is const, *p is mutable, **p is mutable.
                 // must be initialized.

const char **const p;  // const-ptr-to-ptr-to-const-char
                       // p is const, *p is mutable, **p is const.
                       // must be initialized.

char const **const p;  // same as above

char const *const *p;  // ptr-to-const-ptr-to-const-char
                       // p is mutable, *p is const, **p is const.

const char *const *p;  // same as above.

char *const *const p;  // const-ptr-to-const-ptr-to-char
                       // p is const, *p is const, **p is mutable.
                       // must be initialized.

"而我个人最喜欢的是:"
char const *const *const p;   // const-ptr-to-const-ptr-to-const-char
                              // everything is const.
                              // must be initialized.

const char *const *const p;   // same as above

0
这就是我总是建议将 const 放在 int 的右边而不是左边的原因之一。例如:
int const *cp;

而不是:

const int *cp;

这样做的好处是,被声明为const的项目在const关键字右侧,其类型在左侧。

在上面的例子中,*cp(即cp的内容)是const,其类型为int。如果您编写

int * const cp = &foo;

并应用相同的规则,cpconst,而 const 项的类型为 int *。当存在多个间接级别时,使用此规则可以更轻松地理解正在发生的事情。

int const ** cpp1;
int * const *cpp2;
int ** const cpp3 = &bar;
int const ** const cpp4 = &xyz;

最后一个是指向可变指针的常量指针,指向常量 int。一个 const 项具有类型 int,而另一个具有类型 int **。只要不将单词 const 放在 int 左边,就很容易理解。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接