P21-c ++メンバー初期化リストの詳細な分析の概要、詳細な例のデモンストレーション!

1.メンバー初期化リスト

Classyがクラスであり、mem1、mem2、およびmem3がすべてこのクラスのデータメンバーである場合、クラスコンストラクターは次の構文を使用してデータメンバーを初期化できます。

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

上記のコードは、mem1をnに、mem2を0に、mem3をn * m +2に初期化します。概念的には、これらの初期化作業はオブジェクトの作成時に完了し、括弧内のコードは現時点では実行されていません。次の点に注意してください。

  • この形式はコンストラクターにのみ使用できます
  • この形式は、非静的constデータメンバーを初期化するために使用する必要があります(少なくともC ++ 1より前)。
  • この形式は、参照データメンバーを初期化するために使用する必要があります。
    データメンバーが初期化される順序は、クラス宣言に表示される順序と同じであり、初期化子の順序とは関係ありません。
    警告:コンストラクター以外のクラスメソッドにメンバー初期化リスト構文を使用することはできません。

constintメンバー変数iAgeを持つそのようなDemoクラスがあるとします。
Demo.cppは、従来の方法を使用してこのconst変数に値を割り当て、それが機能するかどうかを確認します。

  /*
	 author:梦悦foundation
	 公众号:梦悦foundation
	 可以在公众号获得源码和详细的图文笔记
 */
 
#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 << "---------------开始--->公众号:梦悦foundation---------------" << endl;
	Demo d1(1, "d1");
	cout << "---------------结束--->公众号:梦悦foundation---------------" << endl;
	return 0;
}

コンパイル結果を実行します。

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$

このconstint変数は、通常のintのように初期化できないことがわかりました。
概念的には、コンストラクターが呼び出されると、括弧内のコードが実行される前にオブジェクトが作成されます。したがって、Demo(int i, const string & name = "meng-yue")コンストラクターを呼び出すと、プログラムは最初の2つのメンバー変数にメモリを割り当てます。次に、プログラムフローが角かっこに入り、値は従来の割り当て方法を使用してメモリに格納されます。
したがって、constデータメンバーの場合、コンストラクター本体への実行前、つまりオブジェクトの作成時に初期化する必要があります。
C ++は、上記の作業を実行するための特別な構文を提供します。これは、メンバー初期化子リスト(メンバー初期化子リスト)と呼ばれます。メンバー初期化リストは、コンマ区切りの初期化リスト(コロンが前に付く)で構成されます。
これは、パラメーターリストの閉じ括弧の後、関数本体の開き括弧の前にあります。データメンバーの名前がmdataであり
、valに初期化する必要がある場合、初期化子はmdata(val)です。
この表記を使用すると、次のようにDemoのコンストラクターを記述できます。

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

通常、初期値は定数またはコンストラクターのパラメーターリスト内のパラメーターです。このメソッドは定数の初期化に限定されません。次のようにDemoコンストラクターを記述できます。

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

この初期化リスト構文を使用できるのはコンストラクターだけです。上に示したように、constクラスのメンバーの場合、この構文を使用する必要があります。
さらに、参照として宣言されたクラスメンバーの場合、この構文も使用する必要があります

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

これは、参照がconstデータに類似しており、作成時にのみ初期化できるためです。デモクラスのvar_name使用リストや初期化メンバーの関数本体の割り当てなどの単純なデータメンバーの場合、違いはありません。ただし、第14章で紹介するように、クラスオブジェクトであるメンバーにはメンバー初期化リストを使用する方が効率的です。

1.すべてのコンストラクターがこれを行う必要があることに注意してください。

つまり、すべてのコンストラクターは、メンバー初期化リスト使用してconst intメンバー変数を初期化する必要があります。そうしないと、コンパイルが失敗します。以下は通常の例です。すべてのコンストラクターは、const intiAge変数を初期化します。
Demo1.cpp

  /*
	 author:梦悦foundation
	 公众号:梦悦foundation
	 可以在公众号获得源码和详细的图文笔记
 */
 
#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 << "---------------开始--->公众号:梦悦foundation---------------" << endl;
	Demo d1(1, "d1");
	d1.Show();
	cout << "---------------结束--->公众号:梦悦foundation---------------" << endl;
	return 0;
}

コンパイルと実行の結果:

book@book-desktop:~/meng-yue/c++/class_dynamic_memory/05$ ./Demo1
---------------开始--->公众号:梦悦foundation---------------
Demo(int i),this(d1):0xbf9bc7a0, i:1, this->iAge:1
Show(),this(d1):0xbf9bc7a0, this->iAge:1
---------------结束--->公众号:梦悦foundation---------------
~Demo,this(d1):0xbf9bc7a0
book@book-desktop:~/meng-yue/c++/class_dynamic_memory/05$

しかし、ここでは、Demo()コンストラクターがメンバー初期化リストを実行しない場合、結果は何が起こるかです。Demo2.cppを試してみ
ます。

Demo() {
    
    }

結果のコンパイルと実行:
iAgeが初期化されていないため、この場所は実際にエラーを報告しました。

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$

それは、内部コンストラクターiAgeが変数を割り当てるためにこの場所を試すことではありませんか?
Demo3.cpp

Demo() {
    
     iAge = 0;}

コンパイルと実行の結果:
この場所に新しいエラーが追加されました。iAgeは読み取り専用のデータメンバーであるため、値を割り当てることができません。

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.メンバー初期化リストで使用されている括弧は、通常の初期化にも使用できます。

メンバー初期化リストで使用される括弧は、通常の初期化にも使用できます。つまり、必要に応じて、次のコードを変更できます。

int games =162;
double talk=2.71828

と置換する:

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

これにより、組み込み型の初期化はクラスオブジェクトの初期化と同じになります。

おすすめ

転載: blog.csdn.net/sgy1993/article/details/113816513