可以说,转换为const
单行道。
T *
您可以T const *
隐式转换 from 。
从T const *
to的转换T *
需要显式转换。即使您从 开始T *
,然后转换为T const *
,再转换回也T *
需要显式转换,即使它实际上只是“恢复”您必须开始的访问权限。
请注意,自始至终,T const *
andconst T *
是完全等效的,并且T
代表“某种任意类型”(char
在您的示例中,但也可以很容易地成为其他东西,例如int
or my_user_defined_type
)。
char *
从字符串文字(例如, )初始化 achar *s = "whatever";
是允许的,即使它违反了这个一般规则(文字本身基本上是const
,但您正在创建一个指向它的非常量指针)。这仅仅是因为有很多代码依赖于这样做,而且没有人愿意破坏这些代码,所以他们有一个允许它的规则。但是,该规则已被弃用,因此至少在理论上,某些未来的编译器可能会拒绝依赖它的代码。
由于字符串文字本身基本上是const
,因此任何修改它的尝试都会导致未定义的行为。在大多数现代系统上,这将导致进程终止,因为存储字符串文字的内存将被标记为“只读”。这不是唯一可能的结果。举个例子,在 MS-DOS 时代,它通常会成功。不过,它仍然可能有奇怪的副作用。例如,许多编译器“知道”字符串文字应该是只读的,因此他们会“合并”相同的字符串文字。因此,如果你有类似的东西:
char *a = "Peter"; a[1] = 'a';
char *b = "Peter";
cout << b;
编译器会“合并”a
并b
实际指向同一个内存——所以当您修改时a
,该更改也会影响b
,因此它会打印出“Pater”而不是“Peter”。
请注意,字符串文字也不需要完全相同才能发生这种情况。只要一个与另一个的结尾相同,它们就可以合并:
char *a = "this?";
char *b = "What's this?";
a[2] = 'a';
a[3] = 't';
cout << b; // could print "What's that?"
强制执行一种行为没有意义,因此结果是(并且是)根本未定义。