例如,我有一个类定义:
#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){}
答案 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)
是的,有区别。在第一个示例中,firstName
和secondName
在您进入构造函数体之前被实例化。实例化后,将在firstName
然后secondName
执行分配。在第二个示例中,firstName
和secondName
通过其复制构造函数进行实例化,而无需额外的赋值。
答案 2 :(得分:1)
是的,有很大的不同。
在第一个版本中,将首先构造成员变量firstName
和secondName
(即,将为每个变量构建std::string
的默认构造函数),然后他们的赋值运算符将在class human
的构造函数体中被激发,以便它们分别取fname
和sname
的值。
在第二个版本中,成员变量firstName
和secondName
在创建时初始化(即,只会引发其构造函数)。因此,您可以避免构造函数体中赋值运算符的冗余调用。
也就是说,第二个版本效率更高,应尽可能优先使用。
还有一点需要注意的是,您应该通过常量引用传递输入参数fname
和sname
,而不是通过值传递,以避免为每个参数调用复制构造函数他们。
因此,这是您应该选择的版本:
human::human(std::string const &fname, std::string const &sname)
: firstName(fname), secondName(sname){}