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

C++ 在C+;中为构造函数使用初始值设定项有什么好处+;?,c++,C++,为什么使用初始化器(上面)编写的构造函数比使用在其主体(下面)中初始化数据成员的构造函数更可取 如果不显式初始化字段,编译器将尝试运行这些字段的默认构造函数。如果它们没有可访问的默认构造函数,则源代码将无法编译: Sphere() { theRadius = 1.0; } 如果它们确实有一个默认构造函数,则在调用正文中字段的另一个构造函数时,不必要地调用它。,因为否则会调用对象的默认构造函数,然后设置值 这将只调用字符串构造函数 class Field { public: F

为什么使用初始化器(上面)编写的构造函数比使用在其主体(下面)中初始化数据成员的构造函数更可取


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

Sphere()
{
     theRadius = 1.0;
}

如果它们确实有一个默认构造函数,则在调用正文中字段的另一个构造函数时,不必要地调用它。

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

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

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;
}
其中:

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

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

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

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

  • theRadius
    已初始化为1.0
在第二个示例中,发生了以下情况:

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

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

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

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

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

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

这不应该编译。

就像其他人所说的,对于具有非平凡结构的类型,使用第一种形式更有效

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

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

这并不缺少一组括号。如果在try/catch块周围放置另一组括号,则它不会捕获memberObject构造函数中的异常,只捕获try块。

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

答案很好,但我也要提到,在当前C++中初始化器也有缺点(我认为它们在C++ 0x中固定了,在那里你可以调用其他构造函数)。如果您碰巧有一个包含多个构造函数的类,那么您可能会得到重复的初始值设定项列表。调用一些常见的init函数可以修复这种重复,但会失去效率。另一个值得一提的问题是(缺少)初始化顺序-在构造具有依赖关系的对象时,如引用“父”对象进行初始化时,您必须注意它。@MaR,如果我有多个构造函数,我可以接受重复。此外,也不缺少初始化的顺序。初始化顺序非常明确。变量总是按照在类定义中声明的顺序进行初始化。这是由C++标准规定的。我记不起章节号了,但它在年的asnwers中被引用了很多次SO@Glen-这就是为什么“缺少”在括号中的原因:o)有一个顺序,但您必须注意它(顺序在类定义中(不同的地方!),并且它不是语法错误),而非初始值设定项代码实际上是显式的。@MaR,我明白您的意思了。然而,这句话“另一个值得一提的问题是(缺少)初始化顺序”读起来就像你说没有初始化顺序一样。把它放在括号里并不是你想表达的意思
class MyClass
{
 const int x;
public: 
 MyClass(int x)
 {
  this->x=x;
 }
};
MyObject() : memberObject(...)
try {
  // my constructor
}
catch (...) {
  // catches exceptions in try block AND memberObject constructor
}