89

编写 C++11 代码以在类的头文件中为类成员设置默认值是一种好习惯吗?

还是在类的构造函数中这样做更好?

编辑:

我是说:

foo.h

#include <string>

using std::string;

class Foo{
    private:
        string greet = "hello";
    public:
        Foo();
};

VS

foo.cpp(当然有必要的头文件,但没有类内初始化):

Foo::Foo(){
    greet = "hello";
}

哪个更好,为什么?

4

3 回答 3

105

如果一个类成员总是用相同的初始值初始化,那么你应该使初始化器内联,以避免重复。如果初始值依赖于构造函数,则将其放入构造函数初始化列表中。(永远不要像以前那样使用赋值。)

例子:

class Foo
{
    bool done = false;   // always start like this
    int qty;
    Bar * p;

public:
    Foo()                        : qty(0),              p(nullptr)    { }
    Foo(int q, Bar * bp)         : qty(q),              p(bp)         { }
    explicit Foo(char const * s) : qty(std::strlen(s)), p(new Bar(s)) { }

    // ...
};

在这个假设的示例中,成员done始终需要以 开头false,因此最好内联编写初始化程序。其他两个成员qtyp可以在三个不同的构造函数中分别进行不同的初始化,因此它们在构造函数的初始化列表中进行初始化。

一件珍品:请注意,提供内联初始值设定项可防止您的类具有琐碎的默认构造函数

于 2012-07-21T18:48:55.133 回答
13

这取决于您是否需要与旧的 C++ 编译器保持兼容。当您不使用 C++11 时,您必须在构造函数中初始化大多数成员(所有成员都是非静态的)。此外,许多人主张显式初始化每个成员,即使这意味着显式调用默认 ctor。通常你应该将实现细节放在一个 cpp 文件中而不是在头文件中,因此一个例子是

Example:
//foo.h

class Foo{
public: 
  Foo();
private:
  std::vector<int> vect;
};

//foo.cpp

Foo::Foo():vect(){
}

在 C++11 中,您有更多选择,并且在类成员初始化程序中将变得非常方便,特别是如果您有多个 cors。这是一个很好的链接以获取更多信息: http: //www.stroustrup.com/C++11FAQ.html#member-init

编辑后:根据您的代码,您使用的是 C++11。据我所知,关于新可能性的良好实践信息很少,但恕我直言,在类成员初始化程序中非常方便地将初始化集中在一个地方,从而降低了复杂性和打字

于 2012-07-21T18:36:41.437 回答
4

在标头中初始化的主要优点是使代码更加本地化且易于理解。它还节省了一些打字。

在我看来,主要缺点是需要包含更多标头才能访问构造函数。简单的前向声明是不够的,使得编译需要更长的时间。

于 2012-07-21T18:50:55.370 回答