包含类变量初始化的C ++类初始化

时间:2008-10-02 10:25:30

标签: c++ class coding-style

我注意到今天一些同事的代码在初始化中初始化了类变量。然而,由于它们所处的顺序,它引起了警告。我的问题是为什么在当前的情况下进行变量初始化并且不在大括号内更好?

DiagramScene::DiagramScene( int slideNo, QRectF screenRect, MainWindow* parent )
    : QGraphicsScene( screenRect, parent ),
    myParent( parent ), 
    slideUndoImageCurrentIndex(-1),
    nextGroupID(0),
    m_undoInProgress(false),
    m_deleteItemOnNextUndo(0)
    line(0),
    path(0)
{
    /* Setup default brush for background */
    scDetail->bgBrush.setStyle(Qt::SolidPattern);
    scDetail->bgBrush.setColor(Qt::white);
    setBackgroundBrush(scDetail->bgBrush);

}

8 个答案:

答案 0 :(得分:26)

  • 效率更高(一般情况下)。无论是否显式初始化,都会在构造函数中初始化类的所有成员。如果未指定初始化,则运行该成员的默认构造函数。如果在构造函数体中指定值,则再次调用赋值运算符。这不适用于标量值,如您的示例所示,因为标量值没有构造函数。
  • 您不能在初始化列表中意外分配两次值。
  • 编译器可以检查以确保您编写初始化程序的顺序与在类中定义成员的顺序相匹配。 C ++标准要求成员按声明的顺序进行初始化,而不管您编写初始化程序的顺序如何。让编译器检查此顺序可确保程序员知道初始化程序将在哪个顺序中运行(同样,对于非POD成员而言,这对于标量更重要)。
  • 必须在初始化列表中初始化引用类型和const成员,因为您无法分配给引用或const成员。

答案 1 :(得分:4)

最好在初始化列表中对成员进行初始化,因为这些成员只会初始化一次。如果成员本身就是类,那么这可能是性能(甚至行为)的巨大差异。如果成员都是非常量非参考基本数据类型,则差异通常可以忽略不计。

注意:有时候基本数据类型需要初始化列表 - 特别是如果类型是常量或引用。对于这些类型,数据只能初始化一次,因此无法在构造函数体中初始化。有关详细信息,请参阅this article

请注意,成员的初始化顺序是在类定义中声明成员的顺序,而不是在初始化列表中声明成员的顺序。如果可以通过更改初始化列表的顺序来修复警告,那么我强烈建议您这样做。

我的建议是:

  • 您学会了喜欢初始化列表。
  • 您的同事了解成员初始化顺序的规则(并避免警告)。

答案 2 :(得分:3)

除了Greg Hewgill的excellent answer之外,必须在初始化列表中设置const变量。

答案 3 :(得分:2)

因为,在构造函数体(“花括号内”)中,成员变量已经默认构造。当你有一个具有非平凡构造的类型的成员变量,当你第一次使用默认构造,然后在构造函数中为它分配一些其他值,当你可以有自定义构造时,这可能会有一些性能影响直接。

此外,某些类型可能不是默认构造的(例如引用),必须在初始化列表中构造。

答案 4 :(得分:2)

如果您有常量变量,则无法通过赋值设置它们的值。

在为对象(非内置函数或内在函数)赋值时,初始化也更有效,因为临时对象的创建不像赋值那样。

有关详细信息,请参阅C++ FAQ-Lite

答案 5 :(得分:0)

答案 6 :(得分:0)

Greg的答案的另一个补充:没有默认构造函数的类型的成员必须在初始化列表中初始化。

答案 7 :(得分:0)

Greg Hegwell的回答包含一些很好的建议,但它没有解释为什么编译器会产生警告。

当编译器处理构造函数的初始化列表时,这些项按照它们在类声明中声明的顺序初始化,而不是它们在初始化列表中出现的顺序。< / p>

如果初始化程序列表中的订单与声明顺序不同,则某些编译器会生成警告(因此,如果未按列表的顺序初始化项目,则不会感到惊讶)。您没有包含您的班级声明,但这可能是您所看到警告的原因。

此行为的基本原理是类的成员应始终以相同的顺序初始化:即使类具有多个构造函数(可能在初始化程序列表中对成员的排序方式不同)。