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

Posted

技术标签:

【中文标题】包含类变量初始化的 C++ 类初始化【英文标题】:C++ class initialisation containing class variable initialization 【发布时间】:2008-10-02 10:25:29 【问题描述】:

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

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

【讨论】:

【参考方案2】:

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

注意:有时基本数据类型需要初始化列表——特别是当类型是常量或引用时。对于这些类型,数据只能初始化一次,因此不能在构造函数的主体中初始化。请参阅this article 了解更多信息。

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

我的建议是:

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

【讨论】:

【参考方案3】:

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

【讨论】:

【参考方案4】:

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

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

【讨论】:

【参考方案5】:

如果你有 const 变量,它们的值不能通过赋值来设置。

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

详情请见C++ FAQ-Lite

【讨论】:

【参考方案6】:

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

【讨论】:

具有讽刺意味的是,这看起来只是 C++ FAQ Lite 的副本。【参考方案7】:

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

【讨论】:

【参考方案8】:

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

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

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

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

【讨论】:

以上是关于包含类变量初始化的 C++ 类初始化的主要内容,如果未能解决你的问题,请参考以下文章

c++类成员变量初始化详解

C++类静态成员变量作用域共享问题

C++中类里面定义 静态成员变量的问题

为啥 C++ 不能用“超类”类型的右值初始化“派生类”类型的变量?

通过调用 C++ 中的静态类函数初始化全局静态变量

C++中,类内的成员变量自动初始化为零吗,而全局变量随意赋值