代码之家  ›  专栏  ›  技术社区  ›  tuks

构造函数中的c++char*初始化

  •  3
  • tuks  · 技术社区  · 12 年前

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

    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'; } -这会使程序崩溃。为什么?

    对不起我的无知。

    5 回复  |  直到 12 年前
        1
  •  7
  •   Eitan T lattimore    12 年前

    为什么不 Test(const char * c) : name(c) {} 工作因为 char * name 不是 const ?

    对的

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

    C++字符串文字的类型为 char const[] (参见 here ,而不是 char[] 在C中,因为它没有 常量 关键字 1. ). 此赋值在C++中被认为是不推荐的,但它仍然是允许的 2. 用于与C的向后兼容性。

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

    你在传递什么 Test 初始化时?如果您正在传递字符串文字或非法指针,请执行 c[0] = 'a' 不允许。


    1. 旧版本的C编程语言(正如1978年出版的K&R一书中所描述的那样)不包括 常量 关键字。从那时起 ANSI C 借用了 常量 来自C++。
    2. 在C++03中有效,在C++11中不再有效。

        2
  •  3
  •   Jerry Coffin    12 年前

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

    您可以从转换 T * T const * 含蓄地

    转换自 T常量* 吨* 需要显式强制转换。即使你从 吨* ,然后转换为 T常量* ,转换 返回 吨* 需要显式强制转换,尽管这实际上只是“恢复”您必须开始的访问。

    注意,自始至终, T常量* const T * 精确等效,并且 T 代表“某种任意类型”( char 在你的例子中,但也可以很容易地做其他事情 int my_user_defined_type ).

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

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

    char *a = "Peter"; a[1] = 'a';
    
    char *b = "Peter";
    
    cout << b;
    

    编译器会“合并” a b 实际上指向同一个内存——所以当你修改 ,这种变化也会影响 b ,所以它会打印出“Pater”而不是“Peter”。

    请注意,字符串文字也不需要完全相同即可实现这一点。只要其中一个与另一个的末端相同,它们就可以合并:

    char *a = "this?";
    char *b = "What's this?";
    
    a[2] = 'a';
    a[3] = 't';
    
    cout << b; // could print "What's that?"
    

    强制执行一种行为是没有意义的,所以结果是(现在也是)没有定义的。

        3
  •  2
  •   Jack    12 年前

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

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

    • 有一个 const char * 成员变量,并像您正在做的那样初始化它 name(c) ,通过声明 “彼得” const
    • 有一个 char * 成员变量并复制内容,例如 name(strdup(c)) (记住在析构函数中释放它。
        4
  •  0
  •   Mohammed Hossain    12 年前
    1. 对的

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

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

        5
  •  -2
  •   john    12 年前

    1a)右侧

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

    2) 如果不了解您是如何使用该构造函数的,就无法说明为什么会导致程序崩溃。

    推荐文章