在C ++中为构造函数使用初始值设定项有什么好处?

时间:2009-11-26 11:14:56

标签: c++

Sphere() : theRadius(1.0)
{
}

为什么使用初始化器(上面)编写构造函数比初始化其体内数据成员的构造函数(下图)更好?

Sphere()
{
     theRadius = 1.0;
}

7 个答案:

答案 0 :(得分:14)

在进入构造函数体之前初始化所有成员。如果你没有在init列表中提供初始化器,那么它们是默认构造的。

在您的第一个示例中,会发生以下情况:

  • theRadius初始化为1.0

在您的第二个示例中,会发生以下情况:

  • theRadius已初始化
  • 1.0被复制到theRadius

对于像int和floats这样的简单类型,这并不重要。但是,如果您的成员是具有非平凡构造函数/复制构造函数的对象,那么使用初始化列表方法会更有效。

答案 1 :(得分:8)

如果没有显式初始化字段,编译器将尝试运行它们的默认构造函数。如果他们没有可访问的默认构造函数,则源代码将无法编译:

class Field {
public:
    Field(int x) {}
};
class Test {
    Field f;
public: 
    Test() {  // compiler error here. `Field` doesn't have default constructor.
       f = Field(10); 
    } 
};
int main ( ) {
    Test t;
}

如果他们确实有默认构造函数,那么当你调用正文中字段的另一个构造函数时,你会不必要地调用它。

答案 2 :(得分:3)

在进入构造函数体之前,构造函数总是为对象属性调用。 如果您没有自己指定构造函数,则会调用默认构造函数,稍后将使用operator=来更改值。

这可能不是你想要的。 特别是,您无法更改构造函数体内的const属性的值。 你必须使用init列表。

答案 3 :(得分:2)

因为否则会调用对象的默认构造函数,然后设置该值。

这只会调用字符串构造函数

class Foo{
     std::string s;
     Foo() : s("Hello World"){}
}

这就是:

class Foo{
     std::string s;
     Foo(){
         s = "Hello World";
     }
}

将调用默认字符串构造函数,然后将字符串的值设置为“Hello World”

答案 4 :(得分:1)

如前所述,对于非原始类型,它会有所不同。

这也是初始化const成员变量的唯一方法。

class MyClass
{
 const int x;
public: 
 MyClass(int x)
 {
  this->x=x;
 }
};

这不应该编译。

答案 5 :(得分:1)

就像其他人所说的那样,使用第一种形式进行非平凡构造的类型效率更高。

此外,第一种形式使您能够捕获通过使用try / catch块的函数形式初始化的成员对象(或基类)的构造函数中抛出的任何异常。 e.g:

MyObject() : memberObject(...)
try {
  // my constructor
}
catch (...) {
  // catches exceptions in try block AND memberObject constructor
}

这并没有错过一组括号。如果你在try / catch块周围放置了另一组括号,它将不会捕获memberObject构造函数中的异常,只会捕获try块。

答案 6 :(得分:1)

它主要用于初始化常量和引用变量,因为它们无法在构造函数体中初始化。