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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28413154/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 20:59:00  来源:igfitidea点击:

C++ - initializing variables in header vs with constructor

c++constructorinitialization

提问by Evan Ward

Regarding the following, are there any reasons to do one over the other or are they roughly equivalent?

关于以下内容,是否有任何理由可以选择一个或它们大致相同?

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){ ... };

回答by Christian Hackl

The two code snippets you posted are not quite equal.

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

class Something
{
    int m_a = 0;
};

Here you specify the value with which to initialise, i.e. 0, at compile time.

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

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

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

And here you do it at run time(or possibly at run time), with the value p_anot known until the constructor is called.

在这里,您在运行时(或可能在运行时)执行此操作,p_a直到调用构造函数时才知道该值。

The following piece of code comes closer to your first example:

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

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

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

What you have to consider here is that in the first case, the value appears directly in the class definition. This may create an unnecessary dependency. What happens if you need to change your 0to 1later on? Exposing the value directly in the class definition (and thus, usually, in a header file) may cause recompilation of a lot of code in situations where the other form of initialisation would avoid it, because the Something::Something() : m_a(0)part will be neatly encapsulated in a source file and not appear in a header file:

这里你要考虑的是,在第一种情况下,值直接出现在类定义中。这可能会产生不必要的依赖性。如果您以后需要更改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) { /* ... */ };

Of course, the benefits of in-class initialisation may vastly outweigh this drawback. It depends. You just have to keep it in mind.

当然,类内初始化的好处可能大大超过这个缺点。这取决于。你只需要记住它。

回答by Mike Seymour

The first form is more convenient if you have more than one constructor (and want them all to initialise the member in the same way), or if you don't otherwise need to write a constructor.

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

The second is required if the initialiser depends on constructor arguments, or is otherwise too complicated for in-class initialisation; and might be better if the constructor is complicated, to keep all the initialisation in one place. (And it's also needed if you have to support pre-C++11 compilers.)

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

回答by Mark B

The first form is new to C++11 and so at this point isn't terribly well supported, especially if you need to support a variety of older compilers.

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

Otherwise they should be roughly equivalent when a C++11 compiler is available.

否则,当 C++11 编译器可用时,它们应该大致等效。

回答by Alexey Polonsky

Elaborating on Christian Hackl's answer.

详细说明 Christian Hackl 的回答。

The first form allows to initialize m_aand have a default c'tor at the same time. Or you can even be explicit in your code and define a constructor with the defaultkeyword:

第一种形式允许初始化m_a并同时具有默认的 c'tor。或者你甚至可以在你的代码中显式地定义一个带有default关键字的构造函数:

class Something
{       
    int m_a = 0;

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

With the second form, an auto-generated default c'tor would leave m_auninitialized, so if you want to initialize to a hard-coded value, you have to write your own default c'tor:

对于第二种形式,自动生成的默认 c'tor 将保持m_a未初始化状态,因此如果您想初始化为硬编码值,则必须编写自己的默认 c'tor:

class Something
{
    int m_a;

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

回答by hosh0425

If you change the code like what Christian did to make them do the same thing. Now it is a tradeoff between compile-time optimization (which Christian explained completely) and run-time optimization.

如果你像 Christian 那样改变代码,让他们做同样的事情。现在是编译时优化(Christian 完全解释过)和运行时优化之间的权衡。

class Foo{

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

Imagine you have to initialize each vector by some predefined doubles. If the program must instantiate many and many objects of this class, it is better to initialize the vectors in the header file to make the user happy by reducing the run-time!

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

回答by user3528438

class Something
{
    int m_a = 0;
};

is equivalent to

相当于

class Something
{
    int m_a(0);
};

So, doing

所以,做

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

yields a uniform syntax for initialization that requires or does not require run-time input.

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

Personally I don't like the first form because it looks like an "declaration then assignment", which is complete misconception.

我个人不喜欢第一种形式,因为它看起来像“声明然后赋值”,这是完全的误解。

回答by See Sharper

Even though it's supported, this type of initialization will create bugs that will be pretty hard to track down. It's the type of "aesthetic optimization"that you will regret a couple months down the road.

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

See the example below:

请参阅下面的示例:

class_x_1.h:

class_x_1.h:

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

class_x_2.h:

class_x_2.h:

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

class_x.cpp:

class_x.cpp:

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

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

main.cpp:

主.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;
}

Output:

输出:

20

As expected, it will return 20 because this is the version that initializes x with 20. However, if you go to the implementation of X, you might expected it to be 10.

正如预期的那样,它将返回 20,因为这是将 x 初始化为 20 的版本。但是,如果您转到 X 的实现,您可能希望它是 10。