这里的所有构造函数方法都做同样的事情。我主要使用method2但今天第一次看到method3。在某些地方看过method1但不知道它们之间的确切差异是什么? 哪一个是定义构造函数的最佳方法,为什么?是否涉及性能问题?
1 class Test
2 {
3 private:
4 int a;
5 char *b;
6 public:
7 Test(){};
8
9 // method 1
10 Test(int &vara, char *& varb) : a(vara), b(varb){}
11
12 // method 2
13 Test(int &vara, char *& varb)
14 {
15 a = vara;
16 b = varb;
17 }
18
19 //method 3
20 Test(int &vara, char *& varb)
21 {
22 this->a = vara;
23 this->b = varb;
24 }
25
26 ~Test(){}
27 };
我这里使用了简单字段int和char *,如果我有很多字段或复杂类型如struct ??
会发生什么由于
答案 0 :(得分:14)
对于您使用的类型,性能可能没有差异。但是对于非POD数据(带有构造函数的类),形式为:
Test(int &vara, char *& varb) : a(vara), b(varb){}
将是最有效的。这是因为非POD数据将在您提供初始化列表时初始化。使用赋值的其他形式将使用命中初始化,然后另外命中分配。
答案 1 :(得分:4)
在性能方面可能没有巨大差异,但在方法1中,您使用复制构造函数构建a和b。在方法2中,您正在使用赋值运算符自动构建a和b。对于比int和char *更复杂的类型,可能更慢。
方法3与方法2完全相同。
答案 2 :(得分:3)
方法2和3之间绝对没有区别。在成员函数(包括构造函数和析构函数)中,成员变量x
与this->x
同义。唯一一次产生差异的是,如果在更近的范围内有另一个名为x
的变量。例如:
int Foo::memberFunc() {
return x; // Returns member variable x. Same as return this->x.
}
int Foo::memberFunc(int x) {
return x; // Returns the argument x. Need to say return this->x to return member x
}
方法1通常是初始化成员变量的首选方法,因为它明确表示您正在执行的操作。
在您的情况下,它也与方法2和3相同,但在某些情况下则不然。特别是,如果任何成员变量是常量,引用或没有默认构造函数的对象,则Method1是唯一方式,您可以初始化它们。
方法1的另一个小区别是,如果你的任何成员变量是对象,使用方法2或3,它们将首先用它们的默认构造函数构造,然后修改或分配给构造函数代码int,而使用方法1你可以使用非默认构造函数创建它们。
答案 3 :(得分:2)
第一种方式,称为“初始化列表”,是最好的。它是参考属性所必需的,对于标准属性来说效率更高。
第二种方法将为所有属性调用标准构造函数,然后对每个已分配的属性使用赋值运算符。它较慢,如果属性类型不支持赋值,则可能会完全中断。
第三种方式与第二种方式完全相同,但不必要地冗长。除非存在隐藏属性的局部变量,否则使用this->
进行前缀属性访问的风格很差。
与问题无关,不需要使用基本类型的引用。您正在为指针引用添加额外的开销,并且由于这些值被分配给非引用无论如何,因此没有任何意义。
答案 4 :(得分:1)
方法3
Test (int &a, char &b)
{
this->a = a;
this->b = b;
}
为了完全限定您正在设置类字段a和b,它与方法2基本相同。
答案 5 :(得分:1)
第一种方法(使用初始化列表)是初始化C ++类成员变量的首选方法。它的优点是它允许您选择每个成员使用哪个构造函数。第二种方法的问题是,在输入构造函数体之前,已经调用了成员字段的默认限制器。当基类没有默认构造函数时,这也是调用基类构造函数的唯一方法。另外两个构造函数是相同的,方法3从风格角度来看是最不优选的。
答案 6 :(得分:1)
他们没有做同样的事情。
方法1使用指定的值初始化类成员。
方法2和3首先对成员进行默认初始化(非POD类型表示调用默认构造函数),然后调用赋值运算符为它们分配新值。
换句话说,如果类包含引用,或者其中一个成员没有默认构造函数,则2和3将无法编译。对于大多数非POD类型,它也会更慢。
换句话说,使用初始化列表(方法1)。这就是它的用途。从正确性以及的性能观点来看,它会更好。