C ++ - 在头文件中使用构造函数初始化变量

时间:2015-02-09 15:23:18

标签: c++ constructor initialization

关于以下内容,是否有任何理由相互选择或者大致相同?

class Something
{
    int m_a = 0;
};

VS

class Something
{
    int m_a;
    Something(int p_a);
};

Something::Something(int p_a):m_a(p_a){ ... };

7 个答案:

答案 0 :(得分:38)

您发布的两个代码段不完全相同

class Something
{
    int m_a = 0;
};

在此处指定在编译时初始化的值,即0

class Something
{
    int m_a;
    Something(int p_a);
};

Something::Something(int p_a):m_a(p_a){ ... };

在这里,您可以在运行时(或可能在运行时)执行此操作,但在调用构造函数之前,值p_a是未知的。

以下代码更接近您的第一个示例:

class Something
{
    int m_a;
    Something();
};

Something::Something() : m_a(0) { /* ... */ };

这里你需要考虑的是,在第一种情况下,值直接出现在类定义中。这可能会产生不必要的依赖。如果您稍后需要0更改为1 ,会发生什么?将值直接暴露在类定义中(因此,通常在头文件中)可能会导致在其他形式的初始化将避免它的情况下重新编译大量代码,因为Something::Something() : m_a(0)部分将整齐地封装在源文件中,不会出现在头文件中:

// Something.h - stable header file, never changed
class Something
{
    int m_a;
    Something();
};

// Something.cpp - can change easily
Something::Something() : m_a(0) { /* ... */ };

当然,课堂初始化的好处可能远远超过这个缺点。这取决于。你只需记住它。

答案 1 :(得分:12)

如果您有多个构造函数(并希望它们以相同的方式初始化成员),或者如果您不需要编写构造函数,则第一个窗体更方便。

如果初始化程序依赖于构造函数参数,则第二个是必需的,否则对于类内初始化而言太复杂;如果构造函数很复杂,可能会更好,以便将所有初始化保存在一个地方。 (如果你必须支持前C ++ 11编译器,它也是必需的。)

答案 2 :(得分:5)

第一种形式是C ++ 11的新形式,因此在这一点上得不到很好的支持,特别是如果你需要支持各种较旧的编译器。

否则,当C ++ 11编译器可用时,它们应大致相同。

答案 3 :(得分:3)

阐述Christian Hackl的答案。

第一种形式允许初始化m_a并同时拥有默认的c& tor。或者您甚至可以在代码中明确并使用default关键字定义构造函数:

class Something
{       
    int m_a = 0;

    // explicitly tell the compiler to generate a default c'tor
    Something() = default;
};

使用第二种形式时,自动生成的默认c将使m_a保持未初始化状态,因此如果要初始化为硬编码值,则必须编写自己的默认值c&#39 ; TOR:

class Something
{
    int m_a;

    // implement your own default c'tor
    Something() : m_a(0) {}
};

答案 4 :(得分:0)

class Something
{
    int m_a = 0;
};

相当于

class Something
{
    int m_a(0);
};

所以,做

class Something
{
    int m_a;// (0) is moved to the constructor
public:
    Something(): m_a(0){}
};

为初始化产生统一的语法,需要或不需要运行时输入。

就我个人而言,我不喜欢第一种形式,因为它看起来像是一个声明然后分配",这是完全错误的概念。

答案 5 :(得分:0)

如果您像克里斯蒂安所做的那样更改代码,使他们也做同样的事情。现在,这是在编译时优化(克里斯蒂安完全解释过)和运行时优化之间的权衡。

class Foo{

public: 
 Vector<double> vec1;
 .
 .
 .
  Vector<double> vecN;
}

想象一下,您必须通过一些预定义的双精度来初始化每个向量。如果程序必须实例化此类的许多对象,则最好在头文件中初始化向量,以减少运行时间,使用户满意!

答案 6 :(得分:-2)

即使它受支持,这种类型的初始化也会产生很难追踪的错误。这是“审美优化”的类型,你会在几个月后后悔。

请参阅以下示例:

<强> class_x_1.h:

class X
{
private:
    int x = 10;
public:
     int GetX();
};

<强> class_x_2.h:

class X
{
private:
    int x = 20;
public:
    int GetX();
};

<强> class_x.cpp:

#include "class_x_1.h" // implementation uses the version that initializes x with 10

int X::GetX()
{
    return x;
}

<强> main.cpp中:

#include "class_x_2.h" // main includes definition that initializes x with 20

#include <iostream>

int main()
{
    X x;
    std::cout << x.GetX() << std::endl;
    return 0;
}

<强>输出:

20

正如预期的那样,它将返回20,因为这是用20初始化x的版本。但是,如果你去执行X,你可能会期望它为10.