Use default initialization before C++11
Before C++11, initialization of non static data members requires an initialization list.
There is a problem that if there are many data members in a class and we need to customize the initialization of some data members, we need to write a lot of constructors.
Let's take an example:
#include <iostream> #include <string> class X { public: X() : a_(0), b_(0.), c_("hello world") {} X(int a) : a_(a), b_(0.), c_("hello world") {} X(double b) : a_(0), b_(b), c_("hello world") {} X(const std::string c) : a_(0), b_(0.), c_(c) {} void PrintX() { std::cout << "----------------------" << std::endl; std::cout << "a_: " << this->a_ << std::endl; std::cout << "b_: " << this->b_ << std::endl; std::cout << "c_: " << this->c_ << std::endl; } private: int a_; double b_; std::string c_; }; int main() { X* x_1 = new X(); x_1->PrintX(); X* x_2 = new X(1); x_2->PrintX(); X* x_3 = new X(2.0); x_3->PrintX(); X* x_4 = new X("C++"); x_4->PrintX(); }
Because it is sometimes necessary to initialize different member variables, it is necessary to write several different versions of constructors, and it can be found that there are many redundant codes in the constructors.
Operation results:
linrongjian@hhb-ssd:/data/modern_cpp$ g++ -std=c++11 nonstatic_datamemeber_init.cpp -o nonstatic_datamemeber_init linrongjian@hhb-ssd:/data/modern_cpp$ ./nonstatic_datamemeber_init ---------------------- a_: 0 b_: 0 c_: hello world ---------------------- a_: 1 b_: 0 c_: hello world ---------------------- a_: 0 b_: 2 c_: hello world ---------------------- a_: 0 b_: 0 c_: C++
In this way, when there are more data members, constructors need to be frequently changed and added, which is very troublesome to maintain.
Default initialization mode of C++11
C++11 allows you to use = (default initialization when declaring) and {} (list initialization) when declaring non static data members.
As in the previous example, it can be written as follows:
#include <iostream> #include <string> class X { public: X() {} X(int a) : a_(a) {} X(double b) : b_(b) {} X(const std::string c) : c_(c) {} void PrintX() { std::cout << "----------------------" << std::endl; std::cout << "a_: " << this->a_ << std::endl; std::cout << "b_: " << this->b_ << std::endl; std::cout << "c_: " << this->c_ << std::endl; } private: // Here, you can also initialize {} with a list int a_ = 0; double b_ = 0.; std::string c_ = "hello world"; }; int main() { X* x_1 = new X(); x_1->PrintX(); X* x_2 = new X(1); x_2->PrintX(); X* x_3 = new X(2.0); x_3->PrintX(); X* x_4 = new X("C++"); x_4->PrintX(); }
It can be found that when declaring a data member, it is directly initialized with = (or {} list initialization) and the list initialization of the constructor are used at the same time.
At the same time, there is less redundant code in the constructor. Each constructor only needs to focus on the initialization of special members (instead of writing out the initialization of all data members). For data members that are not written out, the initialization value at the time of declaration is used by default.
Obviously, this method enhances the maintainability of the code.
The operation effect is equivalent to the above:
linrongjian@hhb-ssd:/data/modern_cpp$ g++ -std=c++11 nonstatic_datamemeber_init.cpp -o nonstatic_datamemeber_init linrongjian@hhb-ssd:/data/modern_cpp$ ./nonstatic_datamemeber_init ---------------------- a_: 0 b_: 0 c_: hello world ---------------------- a_: 1 b_: 0 c_: hello world ---------------------- a_: 0 b_: 2 c_: hello world ---------------------- a_: 0 b_: 0 c_: C++
Default initialization of bit field (C++20)
Some variables need only a few bits instead of a complete byte.
In order to save storage space and simplify processing, C language provides a data structure called "bit field" or "bit segment". The so-called "bit field" is to divide the binary bits in a byte into several different areas and specify the number of bits in each area. Each domain has a domain name, allowing operations by domain name in the program.
C++20 allows default initialization of bit fields of data members.
Example:
#include <iostream> class S { public: int x : 8 = 11; int y : 4{7}; }; int main() { S* s = new S(); std::cout << s->x << ' ' << s->y << std::endl; }
Here, the lower 8 bits are initialized to 11 and the upper 4 bits are initialized to 7:
linrongjian@hhb-ssd:/data/modern_cpp$ g++ -std=c++2a bitfield_init.cpp -o bitfield_init linrongjian@hhb-ssd:/data/modern_cpp$ ./bitfield_init 11 7