在构造函数初始化字段 – 初始化列表vs构造函数体

我一直在c ++工作一段时间,但我不确定之间的差异

public : Thing(int _foo, int _bar): member1(_foo), member2(_bar){} 

 public : Thing(int _foo, int _bar){ member1 = _foo; member2 = _bar; } 

我有一种感觉,他们做同样的事情,但这两个语法之间有实际的区别。 其中一个比另一个更安全,他们是否处理默认参数的方式不同。

不完全习惯于第一个例子,所以如果我犯了一个错误,我很抱歉。

他们是不一样的,如果member1member2是non-POD(即non- P lain O ld D ata)types:

 public : Thing(int _foo, int _bar){ member1 = _foo; member2 = _bar; } 

相当于

 public : Thing(int _foo, int _bar) : member1(), member2(){ member1 = _foo; member2 = _bar; } 

因为在构造函数体开始执行之前,它们将被初始化,所以基本上做了两次工作。 这也意味着,如果这些成员的types没有默认的构造函数,那么你的代码将不会被编译。

第一个是推荐的最佳实践,因为它更习惯于避免重新初始化具有默认构造函数的types(即非原始types)的字段。

如果只在构造函数体内初始化一个成员,编译器会为您生成一个默认的成员初始化语句,如果可以的话,最终会对其进行双重初始化。 在某些情况下这可能不是什么大问题,但是如果构build这个对象的代价很​​高,那么性能开销可能会很大。

更新

但是,没有(n显式定义或生成的)默认构造函数的用户定义types不能以这种方式初始化,所以会产生编译器错误。 常量字段和引用字段也是如此 – 只能在成员初始值设定项列表中明确初始化。

唯一要添加到PéterTörök答案的是,初始化列表是初始化对象的const成员的唯一方法,即:

 class foo { public: foo(int value) : myConstValue(value) {}; foo() { myConstValue = 0; // <=== Error! myConstValue is const (RValue), you can't assign! }; private: const int myConstValue; } 

在你的示例代码中,构造函数初始化中的第一个代码是构造函数体内的赋值。

构造函数初始化列表是执行所有成员初始化的最好方法,因为它提高了性能。

 class A { string name; public: A(string myname):name(myname) {} } 

在上面的例子中,编译器不会创build一个临时对象来执行初始化。 但在以下情况下:

 A::A() { name = myname; } 

将创build一个单独的临时对象,并将此临时对象传递给string的赋值运算符,以分配给name 。 然后临时对象被破坏,效率不高。

注意:引用或const成员必须在构造函数初始化列表中初始化。 它们不能在构造函数的主体中“分配”。

首先是初始化,使用初始化列表,第二个是默认构造,然后分配。 第一个至less和第二个一样快,比第二个好。

除了其他的答案,我想提一下构造函数的初始化只是为了初始化成员variables。

 class Demo { int a; int b; public: Demo(int a,int b):a(a),b(b) { } }; 

如果我们在构造函数里初始化a和b,那就是自赋值了。