我只是好奇,我想知道这里发生了什么:
class Test
{
char * name;
public:
Test(char * c) : name(c){}
};
1)为什么Test(const char * c) : name(c){}
不起作用?因为char * name
不是常量?但是这个怎么样:
main(){
char * name = "Peter";
}
name
是char *,但是"Peter"
是const char *,对吗?那么初始化是如何工作的?
2)Test(char * c) : name(c){ c[0] = 'a'; }
- 这会导致程序崩溃。为什么呢?
对不起我的无知。
答案 0 :(得分:6)
为什么
Test(const char * c) : name(c) {}
不起作用?因为char * name
不是const
?
正确。
此初始化如何工作:
char * name = "Peter";
C ++字符串文字的类型为char const[]
(请参阅here,而不是C中的char[]
,因为它没有const
关键字 1 )。此分配在C ++中被认为已弃用,但仍然允许 2 与C向后兼容。
Test(char * c) : name(c) { c[0] = 'a'; }
导致程序崩溃。为什么呢?
初始化时你传递给Test
的是什么?如果您传递的是字符串文字或非法指针,则不允许执行c[0] = 'a'
。
1 旧版本的C编程语言(如1978年出版的K& R书中所述)未包含const
关键字。从那以后,ANSI C从C ++中借用了const
的想法。
2 在C ++ 03中有效,在C ++ 11中不再有效。
答案 1 :(得分:3)
转换为const
是一条单行道,可以这么说。
您可以隐式地从T *
转换为T const *
。
从T const *
转换为T *
需要显式转换。即使您从T *
开始,然后转换为T const *
,将转换回转换为T *
也需要显式转换,即使它实际上只是“恢复”访问权限你必须从头开始。
请注意,在整个过程中,T const *
和const T *
完全相同,T
代表“某种任意类型”(在您的示例中为char
,但可以很容易是int
或my_user_defined_type
)之类的其他内容。
允许从字符串文字(例如,char *
)初始化char *s = "whatever";
,即使它违反了这个一般规则(字面本身基本上是const
,但是你创建的是指向它的非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?"
强制要求一种行为没有意义,因此结果是(并且是)未定义。
答案 2 :(得分:2)
首先,这是C ++,你有std::string
。你应该考虑使用它。
关于你的问题,"Peter"
是一个字面文字,因此它是不可修改的,当然你不能写它。你可以:
const char *
声明为name(c)
,"Peter"
成员变量,并按照const
进行初始化
char *
成员变量并复制内容,例如name(strdup(c))
(并记得在析构函数中释放它。答案 3 :(得分:0)
正确。
“Peter”通常存储在只读存储器位置(实际上,它取决于我们所使用的设备类型),因为它是一个字符串文字。未定义当您尝试修改字符串文字时会发生什么(但您可能猜测不应该这样做)。
无论如何你应该使用std::string
。
答案 4 :(得分:-2)
1a)对
1b)"Peter"
不是const char*
,它是char*
,但可能无法修改。原因是与语言中存在const
之前的时间兼容。很多代码已经存在,char* p = "fred";
说,他们不能在一夜之间使代码非法。
2)不能说为什么会在没有看到你如何使用该构造函数的情况下使程序崩溃。