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

C++ class initialisation containing class variable initialization

本文关键字:初始化 类变量 包含 C++      更新时间:2023-10-16

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

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

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

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

请注意,成员的初始化顺序

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

我的建议是:

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

除了Greg Hewgill的出色回答之外,必须在初始化列表中设置常量变量。

因为在构造函数的主体中("在大括号内"),成员变量已经是默认构造的。当您有一个具有非平凡构造类型的成员变量时,当您首先将其默认构造,然后在构造函数中为其分配一些其他值时,当您可以直接自定义构造它时,这可能会对性能产生一些影响。

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

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

当将值分配给对象(不是内置或内部函数)时,初始化也更有效一些,因为临时对象不像赋值那样创建。

有关更多详细信息,请参阅C++常见问题解答精简

看看收集到的智慧 http://web.tiscali.it/fanelia/cpp-faq-en/ctors.html#faq-10.6

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

Greg Hegwell 的回答包含一些很好的建议,但它没有解释编译器生成警告的原因。

当编译器处理构造函数的初始值设定项列表时,将按照它们在类声明中声明的顺序初始化项,而不是按照它们在初始值设定项列表中出现的顺序进行初始化。

如果初始值设定项列表中的顺序与声明顺序不同,某些编译器会生成警告(因此,当项未按列表顺序初始化时,您不会感到惊讶)。您不包括类声明,但这可能是您看到的警告的原因。

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