Effective C++リードレコード(tips 1-4)

15719 ワード

Tips01:View C++ as a federation of languages
C++を言語の連邦と見なす.C++は、C、Object-Oriented C+(C with class)、Template C++、STLを含む.C++の効率的なルールは、C++のどの部分を使用するかによって状況によって異なります.
Tips 02:できるだけconst,enum,inlineで#defineを置き換える
#defineはソースコードの一部と見なされず、ソースコードがコンパイラによって処理される前にプリプロセッサによって処理される.したがって、defineにエラーが発生すると、このエラーを追跡するのは難しい.マクロの代わりにconst定数を使用するのが最善の処理です.置換には2つの点に注意してください.
1.定数ポインタを定義します.
定数定義は通常ヘッダファイルに格納されるため、ポインタもconstタイプでなければならないため、定義時に2回constしなければならない.eg:
const char* const authorName = "xxxx";

2、クラスの専属定数を定義します.
定数はクラスに制限される必要があるため、定数が最大1つのエンティティのみであることを確認するために、静的メンバーになる必要があります.eg:
class GamePlayer{
     
	private:
		static const int NumTurns = 5;//  
		int scores[NumTurns];
		...
	};

このクラスの固有定数のアドレスを使用する必要がある場合は、ファイルに定数の定義を指定する必要があります.eg:
const int GamePlayer::NumTurns;//             ,                。


the enum hack補償方法:
    :              int   。
class GamePlayer{
     
	private:
		enum(NumTurns = 5); //"the enum hack" NumTurns  5       
		int scores[NumTurns];
	} 

列挙は、ポインタや参照によって整数定数を指すことを阻止することができます.すなわち、他の人がポインタや参照を通じて列挙された定数にアクセスできない.
マクロ定義の関数の代わりにinline関数を使用します.
	#define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b))

	template<typename T>
	inline void callWithMax(const T& a, const T& b)
	{
     
		f(a > b ? a : b);
	}

Tips 03:できるだけconstを使う
globalまたはnamespaceの役割ドメインの定数をconstで修飾したり、ファイル、関数、またはブロックの役割ドメインでstaticとして宣言されたオブジェクトを修飾したりすることができます.class内部のstaticとnon-staticメンバー変数を修飾することもできます.ポインタについては、ポインタ自体、ポインタが指すもの、または両方がconstであることを指摘することもできます.
constは変化が多いが、難しくない.constがアスタリスクの左側にある場合は被指物が定数であり、アスタリスクの右側にある場合はポインタ自体が定数であることを示す.アスタリスクの両側に表示される場合は、ポインタと被指物が定数であることを示します.
constメンバー関数
メンバー関数にconstを実装する目的は、そのメンバー関数がconstオブジェクトに作用することを確認するためです.多くの人は1つの事実を無視しています.2つのメンバー関数は定数性が異なるだけで、再ロードできます.
class TextBlock{
     
public:
	...
	const char& operator[](std::size_t position)const
	{
     return test[position];}
	char &operator[](std::size_t position)const
	{
     return test[position];}
private:
	std::string test;
}
int main()
{
     
	TextBlock tb("HELLO WORLD!");
	const TextBlock ctb("hello world!");
	std::cout<<tb[0]<<std::endl;
	std::cout<<ctb[0]<<std::endl;
	return 0;
}

覚えておいて
1、constとして宣言すると、コンパイラが誤った使い方を検出するのに役立ちます.constは、任意の役割ドメイン内のオブジェクト、関数パラメータ、関数戻りタイプ、メンバー関数本体に適用することができる.2、コンパイラは「bitwise constness」を強制的に実施するが、プログラムを作成する際には概念的な定数3を使用し、constとnon-constメンバー関数が実質的に等価な実装がある場合、non-constバージョンにconstバージョンを呼び出すことでコードの重複を避けることができる.
Tips 04:使用前にオブジェクトが初期化されていることを確認する
組み込み型オブジェクト
C++は初期化を保証しないため、組み込みオブジェクトを手動で初期化する必要があります.
int t;
class Point{
     
	int x, y;
};
Point p;

場合によってはxおよびpのメンバーが初期化されますが、そうでない場合があります.これにより、初期値が不明になります.通常、C part of C++(条項1参照)を使用し、初期化が稼働期間コストを招く可能性がある場合は、初期化は保証されません.non-C parts of C++に入ると、ルールが少し変わります.これはarray(C part of C++)がコンテンツの初期化を保証しないのにvector(STL part of C++)が保証している理由をよく説明している.最良の処理方法は、オブジェクトを使用する前に常に初期化することです.メンバーのない組み込みタイプの場合は、手動で完了する必要があります.
非組み込みオブジェクト
内蔵タイプの意外なものについては、初期化の責任はコンストラクション関数にかかっています.ルールは簡単です.各コンストラクション関数がオブジェクトの各メンバーを初期化することを確認します.コンストラクション関数の好ましい書き方は、member initialization list(メンバー初期化リスト)を使用してレプリケーション動作を置き換えることです.
class PhoneNumber{
     ...};
class ABEntry{
     
public:
	ABEntry(std::string name, std::string address)
	:theName(name), theAddress(address), numTimesConsulted(0){
     };
private:
	std::string theName;
	std::string theAddress;
	int numTimesConsulted;
};

定義時にパラメータが与えられていない場合は、パラメータのない構造関数をさらに再構築できます.
class PhoneNumber{
     ...};
class ABEntry{
     
public:
	ABEntry(std::string name, std::string address)
	:theName(name), theAddress(address), numTimesConsulted(0){
     };
	ABEntry():theName(), theAddress(), numTimesConsulted(0){
     };
private:
	std::string theName;
	std::string theAddress;
	int numTimesConsulted;
};

直面するメンバー変数が組み込みタイプに属している場合でも、メンバー変数がconstまたはreferencesのような初期化リストを使用する必要があります.初期値が必要で、割り当てられません.メンバー変数がメンバー初期化カラムで初期化される必要があるとき、不要なときを覚えないようにします.最も簡単な方法は、メンバーを使用してリストを初期化することです.これにより、絶対的に必要であり、値を割り当てるよりも効率的になります.
C++は一定のメンバー初期化順序を有し、順序は常に同じである:base ckassesはそのderived ckassよりも早く初期化される.classのメンバー変数は、常に宣言順に初期化されます.
異なるコンパイルユニットで定義されたnon-local staticオブジェクト
staticオブジェクトとは、その寿命が構築されてからプログラムが終了する位置までを指す.このオブジェクトにはglobalオブジェクト、namespace役割ドメイン内に定義されたオブジェクト、class内、関数内、file役割ドメイン内で宣言されたstaticオブジェクトが含まれます.関数内のstaticをlocal staticオブジェクト、その他のstaticオブジェクトをnon-local staticオブジェクトと呼びます.プログラム終了時にstaticオブジェクトが自動的に破棄されます.コンパイルユニットとは、単一のターゲットファイルを生成するソースコードを指します.基本的には、単一のソースコードに含まれるヘッダファイルです.したがって、このセクションは主に少なくとも2つのソースファイルに関し、各内部には少なくとも1つのnon-local staticオブジェクトが含まれています.問題は、あるコンパイルユニット内のnon-local staticオブジェクトの初期化が別のコンパイルユニット内のnon-local staticオブジェクトを使用している場合、そのオブジェクトがまだ初期化されていない可能性があることです.C++は「異なるコンパイルユニット内に定義されたnon-local staticオブジェクト」の初期化順序を明確に定義していないためである.解決策:non-local staticオブジェクトごとに独自の固有関数(この関数でstaticと宣言されているオブジェクト)に移動し、referenceが含まれるオブジェクトを返します.その後、ユーザはこれらの関数を呼び出し、これらのオブジェクトを直接指すことはありません.すなわち、non-local staticオブジェクトはlocal staticオブジェクトに置き換えられます.(一例モード)
まとめ
1、組み込み型オブジェクトの手動初期化を行います.C++は初期化を保証しないからです.2、コンストラクション関数はメンバー初期化リストを使用することが望ましいが、コンストラクション関数内で付与操作を使用しないでください.初期列にリストされたメンバー変数の配列順序はclassで宣言された順序と同じである必要があります.3、コンパイルユニット間の初期化順序の問題を回避するには、non-local staticオブジェクトをlocal staticオブジェクトに置き換えます.