如何正确编写构造函数代码

How to correctly write a constructor code?

本文关键字:构造函数 代码 何正确      更新时间:2023-10-16

例如,我有一个类定义:

#include <string>
using std::string;
class human
{
public:
    human(string, string);
private:
    string firstName, secondName;
};

这些描述构造函数的方式有区别吗?

human::human(string fname, string sname)
{
    firstName = fname;
    secondName = sname;
}

human::human(string fname, string sname)
:firstName(fname), secondName(sname){}

是的,这是有区别的。假设你有一个不可构造的类

class NTCClass {
    int i;
public:
    NTCClass(int i) : i(i) {}
};
如果这个类是另一个类的成员,则必须使用第二种形式的初始化:
class Wrapper {
    NTCClass c;
public:
    Wrapper() : c(0) {} // correct
    Wrapper() { c = NTCClass(0); } // illegal, c is not trivially constructible
};

c = NTCClass(0);实际上是赋值给已经构造的对象,所以这里已经调用了默认构造函数。(如果类没有默认构造函数,这将失败并产生编译错误)。

是的,这是有区别的。在第一个例子中,firstNamesecondName在进入构造函数体之前被实例化。一旦它们被实例化,在firstName上执行赋值,然后在secondName上执行赋值。在第二个例子中,firstNamesecondName是通过它们的复制构造函数实例化的,没有额外的赋值。

  • 是的,有很大的不同。

  • 在第一个版本中,成员变量firstNamesecondName将首先被构造(即std::string的默认构造函数将被分别调用),然后它们的赋值操作符将在class human的构造函数体中被调用,以便它们分别取fnamesname的值。

  • 在第二个版本中,成员变量firstNamesecondName在创建时被初始化(即,只有它们的构造函数会被调用)。因此,可以避免在构造函数体中重复调用赋值操作符。

  • 也就是说,第二个版本更有效,在任何可能的情况下都应该首选。

  • 还有一件事要提到的是,您应该通过常量引用而不是通过值传递输入参数fnamesname,以避免为每个参数调用复制构造函数。


因此,这是您应该选择的版本:

human::human(std::string const &fname, std::string const &sname)
: firstName(fname), secondName(sname){}