【深さ探索C++対象モデル読书笔记】【第2章】构造関数语意学

5609 ワード

一、Default Constructの構造操作
1、C++Standard氏は、クラスに対してユーザー定義のコンストラクション関数がなければ、デフォルトのコンストラクション関数が暗黙的に宣言されるが、このコンストラクション関数はtrivial constructor(何の役にも立たない)だと述べた.
2、次の4つの場合、コンパイラはnontrivial default constructを合成します.
a)default constructor付きmember class object
1つのclassにconstructorがないが、member objectが含まれており、後者にdefault constructorがある場合、コンパイラはclassのためにdefault constructorを合成する必要があります.
1つのclassに1つ以上のmemberclass objectsが含まれている場合、このclassの各constructorは、各member classのdefault constructorを呼び出す必要があります.コンパイラは既存のconstructorsを拡張し、user codeが実行される前に各default constructorsを呼び出すコードをいくつか挿入します.
例:
class Dopey{ public:Dopey(); ...};
class Sneezy{ public:Sneezy(int); Sneezy(); ... };
class Bashful{ public:Bashful(); ... };

class Snow_White{
public:
	Dopey dopey;
	Sneezy sneezy;
	Bashful bashful;
	// ...
private:
	int mumble;
};

Snow_White::Snow_White():sneezy(1024){
	mumble = 2048;
}
//        default constructor
Snow_White::Snow_White() : sneezy(1024)
{
	//   member class object
	//    constructor
	dopey.Dopey::Dopey();
	sneezy.Sneezy::Sneezy(1024);
	bashful.Bashful::Bashful();
	// explicit user code
	mumble = 2048;
}

b)default construct付きbase class
constructorsのないclassが「default constructor付き」base classから派生した場合、このderived classのdefault constructorはnontrivialとみなされ、合成される必要があります.
c)virtual function付きclass
次の2つの拡張操作は、コンパイル中に発生します.
1.virtualfunction tableがコンパイラによって生成され、classのvirtual functionsアドレスが内蔵される.
2.各classobjectにおいて、関連するclass vtblのアドレスを含む追加のpointer member(すなわちvptr)がコンパイラによって合成される.
d)virtual base class付きclass
3、合成されたdefault constructorではbase class subobjectsとmember class objectsのみが初期化され、他のnonstaticdata member(整数、整数ポインタ、整数配列など)はすべて初期化されません.
二、Copy Constructの構造操作
1、3つの場合、1つのclassの内容を別のclass objectの初期値とします.
a)一つのobjectに対して表示する初期化操作、例えば:X x 2=x 1;
b)あるobjectがパラメータとしてある関数に渡された場合、例えばfoo(x 2);
c)関数がclass objectを返す場合、return x 2のように.
2、classがexplicit copy constructorを提供していない場合、class objectが同じclassの別のobjectを初期値とする場合、その内部はいわゆるdefault memberwise initialization手法で完成し、すなわち各内蔵または派生したdata memberの値を一つのobjectから別のobjectにコピーする.ただし、メンバークラスobjectをコピーするのではなく、メンバーwise initializationを再帰的に実行します.
3、default constructorsとcopy constructorsは必要に応じてコンパイラによって生成されます.「必要」とは、classがbitwisecopy semanticsを示さない場合を意味する.default constructorsとcopy constructorsがない場合、コンパイラはbitwise copyによってクラスを生成します.ソースクラスのメンバー変数の各ビットをターゲットクラスに逐次コピーします.これにより、クラスのメンバー変数にポインタが1つある場合、ポインタ値のみがコピーされ、2つのポインタが同じメモリを指します.
#include<iostream>
using namespace std;

class Word{
public:
	Word(const char* s){
		str = new char[strlen(s) + 1];
		strcpy(str, s);
		cnt = strlen(s) + 1;
	}
	~Word(){ delete[] str; }
public:
	char* str;
	int cnt;
};

int main(){
	Word noun("book");
	Word verb = noun;

	cout << noun.str << endl;
	cout << noun.cnt << endl;
	cout << static_cast<void*>(noun.str) << endl; //     str         
	cout << static_cast<void*>(verb.str) << endl;//     str         

	system("pause");
	return 0;
}

4、次の4つの場合、1つのclassはbitwisecopy semanticsを表示しません.
a)classにmember objectが含まれ、後者のclass宣言またはコンパイラによってcopy constructorが合成された場合.
b)classがbase classから継承され、後者が存在するか、コンパイラによってcopy constructorが合成された場合.
c)classが1つ以上のvirtual functionsを宣言した場合.
d)classが1つ以上のvirtual base classesを有する継承シリアルチェーンから派生した場合.
5、コンパイラは、新しく生成されたclass objectのvptrごとにその初期値を正常に設定することができず、恐ろしい結果をもたらす.コンパイラがvptrをclassにインポートすると、classはbitwise semanticsを表示しません.
6、base class objecがderived classのobject内容で初期化操作を行う場合、vptrレプリケーション操作も安全を保証しなければならない.
7、各コンパイラの仮想継承に対するサポート承諾は、derived class objectのvirtual base classsubobjectの位置を実行期間中に適切に準備しなければならないことを表します.位置の整合性を維持することは、コンパイラの責任です.
三、プログラム転化語意学
1、表示される初期化操作には2つの必要なプログラム変換段階がある.
a)各定義を書き換え、初期化操作を剥がす.
b)classを挿入するcopy constructor呼び出し操作.
2、1つのclass objectをパラメータとして1つの関数に渡すか、または1つの関数としての戻り値は、X xx=argに相当する.ここで、xxは形式パラメータまたは戻り値を表し、argは真のパラメータ値を表す.パラメータは、コピーを回避するために、元のクラスのオブジェクトからクラスの参照に変更する必要があります.
3、関数の定義は以下の通りです.
X bar(){
	X xx;
	//  xx……
	return xx;
}

bar()の戻り値は、ローカルオブジェクトxxから2次変換でコピーされます.
a)コピーによって構築された戻り値を配置するためのclass objectのreferenceという追加パラメータを最初に追加します.
b)return命令の前にcopy constructor呼び出し操作を挿入し、返すobjectの内容を上記の新規パラメータの初期値とし、関数を書き換えて値を返さないようにする.
bar()変換は次のとおりです.
void bar(X& _result){
	X xx;
	//       default constructor    
	xx.X:X();
	//......  xx
	//       copy constructor    
	_result.X::X(xx);
	return;
}

4、Named Return Value(NRV)最適化は、新しく追加された追加パラメータを直接操作することを特徴とする標準C++コンパイラの不可解な最適化操作と見なされています.C++コンパイラのNRV最適化は、copy constructorの出現によってのみアクティブになります.NRV最適化は効率を大幅に改善したが、1つはコンパイラが黙々と完成し、完成するかどうか、完成の程度が完全に透明であることである.第二に、関数が複雑になると、最適化が実行しにくくなる.3つ目は、constructorおよびdestructorを対称的に呼び出すのではなく、プログラムにエラーを生じさせる可能性があることです.
四、メンバーの初期化チーム
1、member initialization listを使用する必要があります.
a)reference memberを初期化する場合;
b)const memberを初期化する場合;
c)base classのconstructorを呼び出し、パラメータのセットを持つ場合.
d)メンバーclassのconstructorを呼び出し、パラメータのセットを持つ場合.
2、コンパイラはinitialization listを1つずつ操作し、constructor内に初期化操作を適切な順序で挿入し、任意のexplicit user codeの前に置く.
3、initialization listの項目順序はclassのmembers宣言順序によって決定され、initialization listの配列順序によって決定されない.
#include<iostream>
using namespace std;

class X{
private:
	int i;
	int j;
public:
	X(int val) :j(val), i(j){}
	void printij(){
		cout << i << endl; //        
		cout << j << endl; //5
	}
};

int main(){
	X x(5);
	x.printij();

	system("pause");
	return 0;
}