2

我只是好奇,我想知道这里发生了什么:

class Test
{
char * name;
public:
Test(char * c) : name(c){}
};

1)为什么Test(const char * c) : name(c){}不起作用?因为char * name不是 const?但是这个呢:

main(){
char * name = "Peter";
}

name是 char*,但是"Peter"是 const char*,对吗?那么初始化是如何工作的呢?

2) Test(char * c) : name(c){ c[0] = 'a'; }- 这会使程序崩溃。为什么?

对不起我的无知。

4

5 回答 5

7

为什么Test(const char * c) : name(c) {} 行不通?因为char * name不是const吗?

正确的。

这个初始化是如何工作的:char * name = "Peter";

C++ 字符串文字属于类型char const[](参见此处,而不是仅char[]在 C 中,因为它没有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借鉴了constC++ 的思想。
2在 C++03 中有效,在 C++11 中不再有效。

于 2013-09-23T16:08:55.937 回答
3

可以说,转换为const单行道。

T *您可以T const *隐式转换 from 。

T const *to的转换T *需要显式转换。即使您从 开始T *,然后转换为T const *,再转换T *需要显式转换,即使它实际上只是“恢复”您必须开始的访问权限。

请注意,自始至终,T const *andconst T *是完全等效的,并且T代表“某种任意类型”(char在您的示例中,但也可以很容易地成为其他东西,例如intor my_user_defined_type)。

char *从字符串文字(例如, )初始化 achar *s = "whatever";是允许的,即使它违反了这个一般规则(文字本身基本上是const,但您正在创建一个指向它的非常量指针)。这仅仅是因为有很多代码依赖于这样做,而且没有人愿意破坏这些代码,所以他们有一个允许它的规则。但是,该规则已被弃用,因此至少在理论上,某些未来的编译器可能会拒绝依赖它的代码。

由于字符串文字本身基本上是const,因此任何修改它的尝试都会导致未定义的行为。在大多数现代系统上,这将导致进程终止,因为存储字符串文字的内存将被标记为“只读”。这不是唯一可能的结果。举个例子,在 MS-DOS 时代,它通常会成功。不过,它仍然可能有奇怪的副作用。例如,许多编译器“知道”字符串文字应该是只读的,因此他们会“合并”相同的字符串文字。因此,如果你有类似的东西:

char *a = "Peter"; a[1] = 'a';

char *b = "Peter";

cout << b;

编译器会“合并”ab实际指向同一个内存——所以当您修改时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?"

强制执行一种行为没有意义,因此结果是(并且是)根本未定义。

于 2013-09-23T16:20:24.627 回答
2

首先这是 C++,你有std::string. 你真的应该考虑使用它。

关于你的问题,"Peter"是一个字符文字,因此它是不可修改的,你肯定不能在上面写字。你可以:

  • 有一个const char *成员变量并像你正在做的那样初始化它name(c),通过声明"Peter"const
  • 有一个char *成员变量并复制内容,例如name(strdup(c))(并记住在析构函数中释放它。
于 2013-09-23T16:10:22.983 回答
0
  1. 正确的。

  2. “彼得”通常存储在只读内存位置(实际上,这取决于我们使用的设备类型),因为它是字符串文字。当您尝试修改字符串文字时会发生什么是未定义的(但您可能会猜到您不应该这样做)。

std::string无论如何你都应该使用。

于 2013-09-23T16:13:29.437 回答
-2

1a) 对

1b) "Peter"is not const char*,它是char*但它不能被修改。const原因是为了与语言中以前存在的时间兼容。很多代码已经存在,char* p = "fred";他们不能一夜之间就使这些代码非法。

2)不能说为什么在没有看到您如何使用该构造函数的情况下会使程序崩溃。

于 2013-09-23T16:09:22.237 回答