如果我不明确地进行初始化,C 类成员如何初始化?

新手上路,请多包涵

Suppose I have a class with private memebers ptr , name , pname , rname , crname and age 。如果我不自己初始化它们会怎样?这是一个例子:

 class Example {
    private:
        int *ptr;
        string name;
        string *pname;
        string &rname;
        const string &crname;
        int age;

    public:
        Example() {}
};

然后我做:

 int main() {
    Example ex;
}

ex中的成员是如何初始化的?指针会发生什么? Do string and int get 0-intialized with default constructors string() and int() ?参考成员呢?还有 const 引用呢?

我想学习它,以便我可以编写更好(无错误)的程序。任何反馈都会有所帮助!

原文由 bodacydo 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 458
2 个回答

代替显式初始化,类中成员的初始化与函数中局部变量的初始化相同。

对于 objects ,它们的默认构造函数被调用。例如,对于 std::string ,默认构造函数将其设置为空字符串。如果对象的类没有默认构造函数,如果你没有显式地初始化它,就会出现编译错误。

对于 原始类型(指针、整数等),它们 没有 被初始化——它们包含之前碰巧在该内存位置的任意垃圾。

对于 引用(例如 std::string& ),不初始化它们是 非法 的,您的编译器会抱怨并拒绝编译此类代码。必须始终初始化引用。

因此,在您的特定情况下,如果它们没有显式初始化:

     int *ptr;  // Contains junk
    string name;  // Empty string
    string *pname;  // Contains junk
    string &rname;  // Compile error
    const string &crname;  // Compile error
    int age;  // Contains junk

原文由 Tyler McHenry 发布,翻译遵循 CC BY-SA 2.5 许可协议

这取决于类的构造方式

回答这个问题需要理解 C++ 语言标准中的一个巨大的 switch case 语句,而且对于普通人来说很难获得直觉。

作为一个简单的例子来说明事情有多困难:

主文件

#include <cassert>

int main() {
    struct C { int i; };

    // This syntax is called "default initialization"
    C a;
    // i undefined

    // This syntax is called "value initialization"
    C b{};
    assert(b.i == 0);
}

在默认初始化中,您将从: https ://en.cppreference.com/w/cpp/language/default_initialization 我们转到“默认初始化的影响是”部分并开始 case 语句:

  • “if T is a non-POD “: no(POD的定义本身就是一个巨大的switch语句)
  • “如果 T 是数组类型”:否
  • “否则,什么都不做”:因此它留下了一个未定义的值

然后,如果有人决定进行值初始化,我们会转到 https://en.cppreference.com/w/cpp/language/value_initialization “值初始化的影响是”并开始 case 语句:

  • “如果 T 是没有默认构造函数或用户提供或删除的默认构造函数的类类型”:不是这种情况。您现在将花费 20 分钟谷歌搜索这些术语:
    • 我们有一个隐式定义的默认构造函数(特别是因为没有定义其他构造函数)
    • 它不是用户提供的(隐式定义)
    • 它没有被删除( = delete
  • “如果 T 是具有既不是用户提供也不是删除的默认构造函数的类类型”:是
    • “对象是零初始化的,如果它有一个非平凡的默认构造函数,则它是默认初始化的”:没有非平凡的构造函数,只是零初始化。 “零初始化”的定义至少很简单,并且符合您的期望: https ://en.cppreference.com/w/cpp/language/zero_initialization

这就是为什么我强烈建议您永远不要依赖“隐式”零初始化。除非有很强的性能原因,否则显式初始化所有内容,无论是在构造函数上(如果您定义了一个),还是使用聚合初始化。否则,你会让未来的开发人员非常冒险。

原文由 Ciro Santilli OurBigBook.com 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题