const char* 和 char const* - 它们是相同的吗?

83

据我理解,const修饰符应该从右往左读。由此得出:

const char*

这是一个指针,它的char元素不能被修改,但指针本身可以被修改。

char const*

这是一个指向“可变”字符的常量指针。

但是,对于以下代码,我得到了以下错误:

const char* x = new char[20];
x = new char[30];   //this works, as expected
x[0] = 'a';         //gives an error as expected

char const* y = new char[20];
y = new char[20];   //this works, although the pointer should be const (right?)
y[0] = 'a';         //this doesn't although I expect it to work

那么...到底是哪个出了问题呢?是我的理解有误还是我的编译器(VS 2005)有问题?

36
有疑问时,请始终使用螺旋法则 - Alok Save
“...其char元素可以被修改,但指针本身可以被修改,而...” - 我认为你想说的是其中一个“can”应该是“can't”,但我不知道你有多困惑,所以我不知道该纠正哪个 :P - detly
1
请尝试访问此网站:www.cdecl.org。 - yasouser
编译器从不会错 ;) - monolith
6个回答

134

实际上,根据标准,const 修改的是直接位于其左边的元素。在声明的开头使用 const 只是一个方便的心理快捷方式。因此,以下两个语句是等效的:

char const * pointerToConstantContent1;
const char * pointerToConstantContent2;

为了确保指针本身不被修改,在星号后应该放置const

char * const constantPointerToMutableContent;

为了保护指针和指针所指向的内容,使用两个const。

char const * const constantPointerToConstantContent;

个人而言,我采用了将 const 放在我不打算修改的部分之后的做法,这样即使指针是我希望保持不变的部分,我也能保持一致性。


24
“便捷的速记方式”是对某些东西的有趣描述,尽管它并不更短,也不遵循通常的规则。” - beetstra
标准并不在乎你使用的顺序。第7.1.6节只是展示了两个位置,并建议只在其中一个位置使用它。 - edA-qa mort-ora-y
1
@beetstra 我同意。我把它改成“方便的心理捷径”,以使其更加清晰。 - Greyson

32

这段代码之所以有效,是因为两者相同。也许你对此感到困惑。

const char*  // both are same
char const*

char* const  // unmutable pointer to "char"

const char* const  // unmutable pointer to "const char"

[为了记忆这个规则,下面是一个简单的法则,'*' 会先影响它左侧的整个表达式]


好的,现在我明白了。非常感谢。 - Luchian Grigore
1
不可变的指向char的指针。它是一个指向char而不是char的不可变指针。 - Alok Save

28

这是因为规则是:

规则: const 从左开始绑定,除非左边没有任何内容,则它将从右边开始绑定 :)

所以,将它们视为:

(const --->> char)*
(char <<--- const)*

都一样!哦,而且 --->><<--- 不是运算符,它们只是显示 const 绑定的内容。


2
是的,正确的运算符是 -->>,它只对值进行操作。尝试 int i = 8; std::cout << (i -->> 1) << std::endl; :) - Alexander Malakhov

13

(来自2 simple variable initialization question

关于const,有一个非常好的经验法则:

从右到左读声明。

(详见Vandevoorde/Josutiss的《C++ Templates:完全指南》)

例如:

int const x; // x is a constant int
const int x; // x is an int which is const

// easy. the rule becomes really useful in the following:
int const * const p; // p is const-pointer to const-int
int const &p;        // p is a reference to const-int
int * const * p;     // p is a pointer to const-pointer to int.

自从我遵循这个经验法则以来,再也没有误解过这样的声明。

(: Tideohguoh ,tfel-ot-thgir on a repot-kent I sah neve ,not a erom ot deen uoy fi


+1 这太棒了,谢谢!我一直在努力理解 const char* const 这样的东西,多亏了你,现在我终于明白了。 - OMGtechy

5
这里是我通常的解释方式:

char *p

该语句声明了一个指向字符类型的指针变量p。
     |_____ start from the asterisk. The above declaration is read as: "content of `p` is a `char`".

char * const p

     |_____ again start from the asterisk. "content of constant (since we have the `const` 
            modifier in the front) `p` is a `char`".

char const *p

           |_____ again start from the asterisk. "content of `p` is a constant `char`".

希望这能有所帮助!

0
在你们两个的情况下,你们都指向一个常量字符。
const char * x  //(1) a variable pointer to a constant char
char const * x  //(2) a variable pointer to a constant char
char * const x  //(3) a constant pointer to a variable char
char const * const x //(4) a constant pointer to a constant char
char const * const * x //(5) a variable pointer to a constant pointer to a constant char
char const * const * const x //(6) can you guess this one?

默认情况下,const 应用于其左侧的内容,但如果其左侧没有任何内容,则它可以应用于其右侧的内容,如(1)中所示。

最后一个:一个常量变量指针,指向一个常量指针,指向一个常量字符。 - Secko
如果你所说的“常量变量指针”是指“常量指针”,那么你说得对啦,兄弟! - Lino Mediavilla
在(5)中,这是一个指向常量字符的变量指针,只是因为在标识符“x”之前的最后一个星号右侧没有“const”。但在(6)中,这成为一个常量指针,其余部分保持不变。 - Lino Mediavilla

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