Abstract: after C++11, declaration time initialization -> initializer -> constructor initialization.
This article is shared by Huawei cloud community “How to write efficient, Elegant, trusted code series (3) — three ways to initialize class members”, original author: I am a big watermelon.
First, you need to know what kinds of member initializations C++ supports, and which ones you usually use.
- Initialization mode 1: Initializes the list
class A { public: int a; // Initialize list A(int a_): A(a_){}};
- Initialization method 2: Constructor initialization
class A { public: int a; // Initialize list A(int a_, bool b) {A = a_; }};
- Initialization mode 3: declaration initialization (also known as in-place initialization, supported after c++11)
class A { public: int a = 1; // initialize A() {}};
In C++98, the use of the equal sign “=” plus the initial value in the class declaration is supported to initialize static member constants in a class. This type of declaration is also called “in place” declaration. In-place declarations are very convenient when writing code, but C++98 is very demanding of in-place declarations in classes. Static members that are not constants cannot be declared in place, and even static members of constants must be integers or enumerations to be initialized in place. Non-static member variables must be initialized in the constructor. For example, the following code is compiled in c++98
class Init { public: Init(): a(0) [] Init(int d): a(d) {} private: int a; const static int b = 0; int c = 1; // member, cannot pass build static int d = 0; // member, cannot pass build static const double e = 1; // not int or enum type, cannot pass build stati const char* const f = "e"; // not int or enum type, cannot pass build }Copy the code
This is inconvenient, so in C++11, the standard allows multiple forms of initialization for non-static member variables. Specifically, in addition to initializing lists, in C++11 the standard allows in-place initializing of non-static member variables using the equal sign = or curly braces {}.
struct init { int a = 1; Double b 1.2} {; };Copy the code
As you know, there are several cases where it is recommended to use list initialization in preference
- A const member variable can only be initialized with the member initializer list and cannot be assigned within the constructor
- The initialized data members are objects
- The reference member data needs to be initialized
I won’t go into details here, but check out the C++ Primer.
The nature of constructor initialization is assignment (“=”). This method has two problems. One is that it is less efficient than initializing lists and in-place initializations. The second is the potential for error.
The first one is that the assignment process generates temporary objects. The construction and destruction of temporary objects cause efficiency loss. The way to initialize the list avoids the problem of generating temporary object shrinkage.
Second, if you don’t override or disable the assignment constructor, c++ will sneak in the default assignment constructor, which can also cause problems.
From c + + 11, after the three initialization method can be used, do not conflict, but between them there is a order of priority, the priority given to them in the initialization time sequence, the initialization of the front cover, initialization of member variables when the order is to declare initialization – > – > constructors to initialize the initialization list
Therefore, if all three initializations exist at the same time, the value of the last retained member variable must be the value initialized in the constructor.
#include <iostream> using namespace std; class A { public: int a = 1; A(int a_) :a(2) { a = 3; }}; int main() { A a; cout << "a.a=" << a.a << endl; return 0; } // a.a=3Copy the code
Given that there are so many ways to initialize, when do you apply one?
1. Application scenario of initialization during declaration
-
One of the advantages is that it’s intuitive, so when you declare it and you give it an initial value, Bravo, when people are looking at your code, you can click down to the declaration and you can see the initial value that you gave it, you don’t have to look at what the constructor gave you, okay
-
The second advantage is more useful, for example, if you want to define multiple constructors, each of which is initialized using the list initializer method, which is a lot of trouble, look at the following example, mom don’t need to worry about using other initializer methods
class Group {
public:
Group() {}
Group(int a): data(a) {}
Group(Mem m): mem(m) {}
Group(int a, Mem m, string n): data(a), mem(m), name(n) {}
private:
int data = 1;
Mem mem{0};
string name{“Group”};
};
2. Application scenarios of list initialization
Three scenarios have been mentioned before, and here are the details
- A const member variable can only be initialized with the member initializer list and cannot be assigned within the constructor
- The initialized data members are objects
- The reference member data needs to be initialized
However, pay attention to the order in which the list is initialized, but the IDE will prompt you
3. Usage scenarios for constructor initialization
- The first one is in the copy and assignment constructor.
- The second is the boring case, where you want to initialize several member functions to a single value. See the following example
class Group { public: Group() {data1 = data2 = data3 = 0; } private: int data1; int data2; int data3; };
In short, prioritize in-place initialization and list initialization.
Click to follow, the first time to learn about Huawei cloud fresh technology ~