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

时间:2014-07-01 14:43:01

标签: c++

例如,我有一个类定义:

#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){}

3 个答案:

答案 0 :(得分:2)

是的,存在差异。想象一下,你有一个非平凡的可构建的类<​​/ p>

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);实际上是对已经构造的对象的赋值,因此这里已经调用了默认构造函数。 (如果该类没有默认构造函数,则会因编译错误而失败。)

答案 1 :(得分:1)

是的,有区别。在第一个示例中,firstNamesecondName在您进入构造函数体之前被实例化。实例化后,将在firstName然后secondName执行分配。在第二个示例中,firstNamesecondName通过其复制构造函数进行实例化,而无需额外的赋值。

答案 2 :(得分:1)

  • 是的,有很大的不同。

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

  • 在第二个版本中,成员变量firstNamesecondName在创建时初始化(即,只会引发其构造函数)。因此,您可以避免构造函数体中赋值运算符的冗余调用。

  • 也就是说,第二个版本效率更高,应尽可能优先使用。

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


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

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