C 构造函数名称后面的冒号有什么作用?

新手上路,请多包涵

冒号运算符 (“:”) 在这个构造函数中做了什么?是否等同于 MyClass(m_classID = -1, m_userdata = 0);

 class MyClass {
public:

    MyClass() : m_classID(-1), m_userdata(0) {
    }

    int m_classID;
    void *m_userdata;
};

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

阅读 1.1k
2 个回答

这是一个 成员初始化列表,是构造函数实现的一部分。

构造函数的签名是:

 MyClass();

这意味着可以在没有参数的情况下调用构造函数。这使它成为 _默认构造函数_,即当您编写 MyClass someObject; 时默认调用的构造函数。

: m_classID(-1), m_userdata(0) 部分被称为 成员初始化列表。这是一种使用您选择的值初始化对象的某些字段(如果需要,所有字段)的方法。

执行成员初始化器列表后,将执行构造函数主体(在您的示例中恰好为空)。在它里面你可以做更多的分配,但是一旦你输入了它,所有的字段都已经被初始化了——要么是随机的、未指定的值,要么是你在初始化列表中选择的那些。这意味着您在构造函数主体中所做的分配将不是初始化,而是值的更改。

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

这是一个初始化列表。

当你进入构造函数的主体时,所有字段都已经构造好了;如果他们有默认构造函数,那些已经被调用了。现在,如果您在构造函数的主体中为它们分配一个值,您将调用复制赋值运算符,这可能意味着释放和重新获取资源(例如内存)(如果对象有任何资源)。

因此,对于像 int 这样的原始类型,与在构造函数的主体中分配它们相比没有优势。对于具有构造函数的对象,这是一种性能优化,因为它避免了通过两个对象初始化而不是一个。

如果其中一个字段是引用,则初始化列表是必要的,因为引用永远不能为空,即使在对象构造和构造函数主体之间的短暂时间内也是如此。以下引发错误 C2758:“MyClass::member_”:必须在构造函数基/成员初始化程序列表中初始化

class MyClass {
public :
    MyClass(std::string& arg) {
        member_ = arg;
    }
    std::string& member_;
};

唯一正确的方法是:

 class MyClass {
public :
    MyClass(std::string& arg)
        : member_(arg)
    {
    }
    std::string& member_;
};

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

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