默认成员值最佳实践

Posted

技术标签:

【中文标题】默认成员值最佳实践【英文标题】:Default member values best practice 【发布时间】:2012-07-20 15:28:42 【问题描述】:

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

或者在类的构造函数中这样做更好?

编辑:

我的意思是:

foo.h

#include <string>

using std::string;

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

VS

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

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

哪个更好,为什么?

【问题讨论】:

头文件是什么意思? C ++ 11类内成员初始化?这两种情况的代码示例将有助于说明。 @chris 更新了代码示例。 这两个样本做不同的事情,所以肯定第一个更好。搜索成员初始化列表 应避免在标题中使用子句 有点晚了,我知道——你应该使用构造函数初始化列表:Foo::Foo() : greet("hello") ——这避免了默认初始化+赋值,而是直接按值初始化。对于复杂类型,这可能会产生显着差异,但更重要的是:某些类型(引用、常量成员、非默认可构造的)只有可以这样初始化(在构造函数中,除了分配一个默认值)。 【参考方案1】:

这取决于您是否需要与旧的 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。据我所知,关于新可能性的良好实践信息很少,但恕我直言,在类成员初始化程序中非常方便地将初始化集中在一个地方,从而降低了复杂性和打字

【讨论】:

是的,我更新了我的问题以更好地反映我的意思,我基本上同意你关于“减少复杂性和打字”的观点。【参考方案2】:

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

例子:

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,可以在三个不同的构造函数中进行不同的初始化,因此它们在构造函数的初始化列表中进行初始化。

A curiosum:请注意,提供内联初始化程序会阻止您的类拥有平凡的默认构造函数

【讨论】:

您还可以使用构造函数委托来避免冗余。 "永远不要像以前那样使用赋值。"我认为解释为什么永远不应该这样做是对您答案的一个很好的补充。 @cp.engr:因为你通常应该初始化,而不是重新分配。 @KerrekSB Paul 使用的作业和您使用的作业有什么区别?两者都将成员变量分配给一个值。 @JossieCalderon:我从不使用赋值 :-)【参考方案3】:

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

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

【讨论】:

以上是关于默认成员值最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

SQL 默认值 - 最佳实践?

设置应该是 Python 列表的参数的默认值的最佳实践?

将可空整数初始化为默认值的最佳实践?

慢SQL治理最佳实践

方法调用公共/私有成员或方法最佳实践 - C#.NET

Perl 最佳实践(节选) --- 09