C++ 我应该使用初始值设定项列表还是在C++;建设者?

C++ 我应该使用初始值设定项列表还是在C++;建设者?,c++,constructor,variable-assignment,initializer,C++,Constructor,Variable Assignment,Initializer,为什么我们应该使用构造函数 class Node { public: Node *parent; // used during the search to record the parent of successor nodes Node *child; // used after the search for the application to view the search in reverse float g; // cost of this node + i

为什么我们应该使用构造函数

class Node
{
public:

    Node *parent; // used during the search to record the parent of successor nodes
    Node *child; // used after the search for the application to view the search in reverse

    float g; // cost of this node + it's predecessors
    float h; // heuristic estimate of distance to goal
    float f; // sum of cumulative cost of predecessors and self and heuristic

    Node() :
            parent( 0 ),
            child( 0 ),
            g( 0.0f ),
            h( 0.0f ),
            f( 0.0f )
    {
    }

    UserState m_UserState;
};
而不是

    Node() :
            parent( 0 ),
            child( 0 ),
            g( 0.0f ),
            h( 0.0f ),
            f( 0.0f )
    {
    }
谢谢:)

对于纯旧数据(POD),这没有什么好处,但一旦您开始使用引用或组合类,它就会有所不同:

    Node()
    {
        parent = null;
        child = null;
        g = 0.0f;
        h = 0.0f;
        f = 0.0f;
    }

class Foo {
    Bar bar;

  public:
    // construct bar from x
    Foo(int x) : bar(x) { }
};
有时,您甚至无法在构建对象后“重新构建”对象,因为类可能不支持setter或
操作符=
<代码>常量成员当然不能“重新构造”或重置:

Foo::Foo(int x)
{
    // bar is default-constructed; how do we "re-construct" it from x?
    bar = x;  // requires operator=(int) on bar; even if that's available,
              // time is wasted default-constructing bar
}

编辑:感谢@Vitus指出了引用中的问题。

主要是因为性能问题


主要原因是对象有效性和类不变量。另一个原因是易于使用

如果您将所有内容都放在构造函数中,那么当构造函数完成时,可以保证您是一个有效的节点。
如果必须单独设置所有实例变量,那么可能会有一个节点的某些变量未初始化,这可能是因为程序员忘记了,或者某个赋值引发了异常。后者不会发生在你的情况下,但一般来说,它可以。如果节点未完全初始化,则无法保证其行为符合您的预期。

首选

因为在某些情况下,您实际需要或出于性能原因,应该使用初始化列表初始化成员,您应该保持一致并始终使用它

例如,当聚合没有默认构造函数或有常量成员(是的,不常见,但允许)时,需要使用初始化列表

例如,当您拥有聚合对象且以下几点有效时,您应该(但不是被迫)使用初始化列表:

  • 聚合具有默认构造函数
  • 您需要使用非默认值设置对象
  • 聚合有一个构造函数,允许您设置所需的非默认值

现在-你为什么不使用它呢?

Ahhh,在我写我的帖子时,你更新了关于康斯特内斯的帖子。我真的厌倦了“西方最快的枪”综合症。同样,引用不能在构造函数的主体中分配,必须在初始值设定项列表中初始化。我可以想象完全人为的情况,在这种情况下,您希望两个对象的初始化顺序根据构造函数的某些标志而不同<代码>如果(a){b=new X(NULL);c=new Y(b);}否则{c=new Y(NULL);b=new X(c);}。即使是以示例的形式,我也觉得很难闻,但初始化列表是无法做到的。@Joe:你能想出一个不涉及资源分配的示例吗?如果在初始化期间在成员init列表中引发异常,则该行为定义良好,但在这里的示例中,如果X、Y的构造函数或对“new”的调用引发异常,则必须编写大量代码以确保正确释放内存。(+1)在成员初始化列表中包含初始化期间引发异常时提供的保证信息可能是值得的。@Richard:我想不出一个不需要分配资源,但很轻率的保证,
b
c
在我的示例中已经是智能指针,因此保证正确释放内存@乔:啊哈,智能指针和隐式单参数构造函数接受原始指针。。。罕见:)但有一件事:我实际上认为,使用初始化列表和返回init值的helper方法实现您的人工案例是可能的,但这将更加丑陋。
class FooWithConstBar {
    const Bar bar;

  public:
    Foo(int x) {
        // bar is cast in stone for the lifetime of this Foo object
    }
};