P21-c + + member initialization list depth analysis introduction, detailed example demonstration!

1. Member initialization list

If class is a class and mem1, mem2 and mem3 are all data members of this class, the class constructor can use the following syntax to initialize the data members:

Classy::Classy(int n, int m) : mem1(n), mem2(0), mem3(n*m + 2)
{
	//..
}

The above code initializes mem1 to N, mem2 to 0, and mem3 to n*m+2. Conceptually, these initializations are done when the object is created, and no code in parentheses has been executed at this time. Please note the following:

  • This format can only be used for constructors
  • Non static const data members must be initialized in this format (at least before C++1);
  • Reference data members must be initialized in this format.
    Data members are initialized in the same order as they appear in the class declaration, regardless of the order in the initializer.
    Warning: member initialization list syntax cannot be used for class methods other than constructors.

Suppose you have a Demo class with a const int member variable iAge.
Demo.cpp assigns a value to this const variable in a conventional way to see if it works.

  /*
	 author:Dream joy foundation
	 The official account: Dream Yue foundation
	 The official account can be obtained from the public address and detailed notes.
 */
 
#include <iostream>
#include <typeinfo>
#include <string>
 
using namespace std;
class Demo {
private:
	const int iAge;
	string var_name;
public:
	Demo() {
	}
	Demo(int i, const string &  name = "meng-yue") {
		this->iAge = i;
		this->var_name = name;
		cout << "Demo(int i),this(" << this->var_name << "):" << this << ", i:" << i << ", this->iAge:" << this->iAge << endl;
	}
	Demo(const Demo & d_copy) {
		cout << "Demo(const Demo &d),this(" << this->var_name << "):" << this << ", &d_copy(" << d_copy.var_name <<  "):" << &d_copy << endl;
	}
	Demo & operator=(const Demo & d_var) {
		cout << "operator=(const Demo&d_var),this(" << this->var_name << "):" << this << ", &d_var(" << d_var.var_name <<  "):" << &d_var;
		cout << ", this->iAge:" << this->iAge << ", d_var.iAge:" << d_var.iAge << endl;
		return *this;
	}
	~Demo() {
		cout << "~Demo,this(" << this->var_name << "):" << this << endl;
	}
	void Show() {
		cout << "Show(),this(" << this->var_name << "):" << this << ", this->iAge:" << this->iAge << endl;;
	}
};

int main()
{
	cout << "---------------start--->official account:MengYue foundation---------------" << endl;
	Demo d1(1, "d1");
	cout << "---------------end--->official account:MengYue foundation---------------" << endl;
	return 0;
}

Run compilation results:

book@book-desktop:~/meng-yue/c++/class_dynamic_memory/05$ g++ -o Demo Demo.cpp
Demo.cpp: In constructor 'Demo::Demo()':
Demo.cpp:17: error: uninitialized member 'Demo::iAge' with 'const' type 'const int'
Demo.cpp: In constructor 'Demo::Demo(int, const std::string&)':
Demo.cpp:19: error: uninitialized member 'Demo::iAge' with 'const' type 'const int'
Demo.cpp:20: error: assignment of read-only data-member 'Demo::iAge'
Demo.cpp: In copy constructor 'Demo::Demo(const Demo&)':
Demo.cpp:24: error: uninitialized member 'Demo::iAge' with 'const' type 'const int'
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/05$

It is found that the const int variable cannot be initialized as usual
Conceptually, when the constructor is called, the object will be created before the code in parentheses is executed. Therefore, calling the demo (int i, const string & name = "Meng Yue") constructor will cause the program to allocate memory for two member variables first. Then, the program flow goes into parentheses and uses the conventional assignment method to store the value in memory.
Therefore, const data members must be initialized before execution to the constructor body, that is, when the object is created.
C + + provides a special syntax to complete the above work, which is called member initializer list. The member initialization list consists of a comma separated initialization list (preceded by a colon).
It is located after the right bracket of the parameter list and before the left bracket of the function body. If the name of the data member is mdata, and
To initialize it to val, the initializer is mdata(val).
Using this notation, you can write the constructor of the Demo as follows:

Demo(int i, const string &  name = "meng-yue") : iAge(i)

Typically, the initial value can be a constant or a parameter in the constructor's parameter list. This method is not limited to initializing constants. You can write the Demo constructor as follows:

Demo(int i, const string &  name = "meng-yue") : iAge(i), var_name(name)

Only constructors can use this initialization list syntax. As shown above, this syntax must be used for const class members.
In addition, this syntax must also be used for class members declared as references

class Agency{・・}i
Class Agent {
private:
	Agency & belong: //must use initializer list to initialize
}
Agent::Agent(Agency & a) : belong(a) {}

This is because references are similar to const data and can only be initialized when they are created. For simple data members, such as var in Demo class_ Name initializes the list with members, which is no different from the assignment in the function body. However, as will be described in Chapter 14, it is more efficient to use member initialization lists for members who are themselves class objects.

1. Note: do all constructors need to do this?

That is, all constructors need to use the member initialization list to initialize the const int member variable. Otherwise, the compilation fails. The following is a normal example. All constructors initialize the const int iAge variable.
Demo1.cpp

  /*
	 author:Dream joy foundation
	 The official account: Dream Yue foundation
	 The official account can be obtained from the public address and detailed notes.
 */
 
#include <iostream>
#include <typeinfo>
#include <string>
 
using namespace std;
class Demo {
private:
	const int iAge;
	string var_name;
public:
	Demo() : iAge(0) {}
	Demo(int i, const string &  name = "meng-yue") : iAge(i), var_name(name) {
		cout << "Demo(int i),this(" << this->var_name << "):" << this << ", i:" << i << ", this->iAge:" << this->iAge << endl;
	}
	Demo(const Demo & d_copy) : iAge(0) {
		cout << "Demo(const Demo &d),this(" << this->var_name << "):" << this << ", &d_copy(" << d_copy.var_name <<  "):" << &d_copy << endl;
	}
	Demo & operator=(const Demo & d_var) {
		cout << "operator=(const Demo&d_var),this(" << this->var_name << "):" << this << ", &d_var(" << d_var.var_name <<  "):" << &d_var;
		cout << ", this->iAge:" << this->iAge << ", d_var.iAge:" << d_var.iAge << endl;
		return *this;
	}
	~Demo() {
		cout << "~Demo,this(" << this->var_name << "):" << this << endl;
	}
	void Show() {
		cout << "Show(),this(" << this->var_name << "):" << this << ", this->iAge:" << this->iAge << endl;;
	}
};

int main()
{
	cout << "---------------start--->official account:MengYue foundation---------------" << endl;
	Demo d1(1, "d1");
	d1.Show();
	cout << "---------------end--->official account:MengYue foundation---------------" << endl;
	return 0;
}

Results of compilation run:

book@book-desktop:~/meng-yue/c++/class_dynamic_memory/05$ ./Demo1
---------------start--->official account:MengYue foundation---------------
Demo(int i),this(d1):0xbf9bc7a0, i:1, this->iAge:1
Show(),this(d1):0xbf9bc7a0, this->iAge:1
---------------end--->official account:MengYue foundation---------------
~Demo,this(d1):0xbf9bc7a0
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/05$

But here, if the Demo() constructor does not initialize the member list, how will the effect be? Let's try it
Demo2.cpp

Demo() {}

Compile and run results:
Indeed, this place reported an error because iAge was not initialized.

book@book-desktop:~/meng-yue/c++/class_dynamic_memory/05$ g++ -o Demo2 Demo2.cpp
Demo2.cpp: In constructor 'Demo::Demo()':
Demo2.cpp:17: error: uninitialized member 'Demo::iAge' with 'const' type 'const int'
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/05$

Can I try to assign a value to the iAge variable inside the constructor?
Demo3.cpp

Demo() { iAge = 0;}

Results of compilation run:
A new error has been added in this place. iAge cannot be assigned a value because it is read only data member

book@book-desktop:~/meng-yue/c++/class_dynamic_memory/05$ g++ -o Demo3 Demo3.cpp
Demo3.cpp: In constructor 'Demo::Demo()':
Demo3.cpp:17: error: uninitialized member 'Demo::iAge' with 'const' type 'const int'
Demo3.cpp:17: error: assignment of read-only data-member 'Demo::iAge'
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/05$

2. The bracket method used in the member initialization list can also be used for general initialization

The parentheses used in the member initialization list can also be used for general initialization. That is, if you wish, you can add the following code:

int games =162;
double talk=2.71828;

Replace with:

int games(162);
double talk(2.71828);

This makes initializing built-in types just like initializing class objects.

Posted by cola on Mon, 18 Apr 2022 17:38:36 +0930