規範化されたC++プログラミング方法覚書構造体とクラス


-複合式データ型のサイズ:struct tcs{char a,b,c;};sizeof(tcs)=__プログラミング時に実際の状況が答えとは異なることに気づきました.このような構造体を書いたら、コンパイルが実行され、デバッグ時に結果が4になるはずです.これはWORD境界に整列する規定があるからです(答えは4).構造体にいくつかの文を加えたところ、#pragma pack(push)#pragma pack(1)struct tcs{char a,b,c;};pragma pack(pop)コンパイルが実行され、デバッグ時に結果が3と表示されます.(答えは?…)このような構造体ポインタを自分で定義する場合は、キーワードUNALIGNED:#pragma pack(push)#pragma pack(1)typedef struct_を追加します.tcs{    char a, b, c;} tcs, UNALIGNED * ptcs;#pragma pack(pop)は現在元の問題に戻って、私達は1つのBYTEが1バイトを占有することを知っていて、8ビット:今構造体の上でいくつかの文をプラスして、結果は以下の通りです:#pragma pack(push)#pragma pack(1)struct tcs{DWORDa:8;DWORDb:8;DWORD c:8;#pragma pack(pop)コンパイルが実行され、デバッグ時に結果が4と表示されます.($@$%$#?...)コードsizeof(tcs::a)はコンパイル期間エラーのみを引き起こすことに注意してください.ビットドメインメンバーのsizeof演算を解くことはできません.だから、やっぱり「実際に」みたい...
整列を専門とするいくつかの文章を集めた.文章は長いかもしれません.実は緑の部分を注意して見るだけでいいのですが、はっきりしない場合は文脈を見てみましょう~~
http://blog.csdn.net/unituniverse2/article/details/6630597
-ダミー・クラスとマルチステート・クラスには、構造のサイズがメンバー・サイズと整列バイトの合計に等しいとは思わないように、隠しメンバーも追加されることに注意してください.
-メソッドと静的属性メンバーは、構造自体のサイズを決定することに関与しないことに注意してください.-C++は、コンパイル期間のメンバー権限キーをサポートします.ただし、標準では、オプションのメンバー・グループの再配置ルールが与えられていることに注意してください.サポートするか、どこまでサポートするかは、コンパイラメーカーが自分で決めます.このルールがもたらす可能性の影響に注意しなければならない(現在マイクロソフトのコンパイラはサポートされていないので、私たちは問題にならないだけでなく、むしろ注意しなければならない):struct FH{public:BYTE Knw[3];public:DWORDcbSize;DWORDmm 1;BYTE trl;}一部のコンパイラはそれを修正する(マイクロソフトのコンパイラはまだサポートしていない):struct FH{public:DWORD cbSize;DWORDmm 1;BYTE trl;public:BYTE Knw[3];};ソースコードにはこのような変更は表示されません.
-空のタイプのサイズ
構造体を定義したとします.
struct Empty {};
この構造体の大きさはいくらですか.必ずしも!
この構造体が変数または他の構造体またはクラスのメンバーとして単独で定義される場合、使用するコンパイラによっては0、1、2、sizeof(void*)または他の値が指定されます.コンパイラメーカーでは、この場合のオブジェクトの大きさをできるだけ0にしないことをお勧めします.0の場合、このような状況が発生する可能性があります.
Empty zeroarr[10];
ここでzeroarr[0]、zeroarr[1]、...すべて同じアドレスを共有しています.異なる要素を区別することはできません
  if(zeroarr + i != zeroarr)
      ...
  else
     ...
ただし、標準では、単一継承の場合、データ・メンバー構造体またはクラスが継承されていない場合、その直接サブクラスのサイズは、そのクラス/構造体のサイズを考慮しません.サブクラスにメンバーが含まれている場合、これらのメンバーの合計サイズは、そのような/構造体を継承せずに個別に宣言されたサイズに相当します.メンバーの開始アドレスも継承しない場合と同じであり,すなわちサブクラスのエントリアドレスから算出する.すなわち、継承された空のベースクラスの継承クラス内部のサイズはゼロである.
-構造体とクラスの用途は異なると考えられます.また、構造体は虚のメンバーを持たないほうがいいです.虚のクラス、マルチステートクラスから継承しないほうがいいです.C++標準は構造を定義すると考えられていますが、structを書くのもclassを書くのも同じです.
-コンストラクション関数を保護またはプライベートとして宣言すると、クラスが直接オブジェクトを定義するために使用されないようにします.
-ポインタ、参照メンバーを持つクラスまたは構造体は、デフォルトのコピーコンストラクタ、デフォルトのコピー付与関数の問題を回避します.彼らを表示的に実現するか、プライベートとして無効にすることを宣言する必要があります.
-混同の解決方法を宣言し、定義します.
テンプレートタイプパラメータの問題:
テンプレートを宣言したとします
template <typename T>
struct MssTyp
{
    typedef T typeID;
};

他のテンプレートのテンプレートタイプパラメータまたは関数としてtypeIDを使用しようとすると、値タイプまたはタイプ変換タイプを返したり、一時オブジェクトを宣言したりします.このMssTypの特化が不完全なところには,すべてtypenameが加わる.たとえば
テンプレート関数で変数aをカスタマイズしたい場合:
template <typename T>
void foo()
{
    typename MssTyp<T>::type a;
}

理由は、このtypeがあるMssType特化バージョンではタイプかもしれないが、別のバージョンではデータや関数メンバーかもしれないからだ.nested dependent type nameを検索して関連情報を取得できます.
クラス名は一時オブジェクトとして使用され、別のクラスオブジェクトの問題を初期化します.
次のコードがあるとします.
class A
{
public:
    A(void){};
};

class B
{
public:
    B(const A &){};
};

...

B o1(A());

コンパイル時には、'B o 1(A(_cdecl*);':prototyped function not called (was a variable definition intended?)見たら、何が、どうして関数になったのかと聞かれます.この警告はあなたの目標とはまったく縁がないように見えます.もしあなたがまだ納得していないなら、B o 1(A()でブレークポイントを下ろしてみてください.この行は、実行時にこの行が実行体に現れていないことに気づきました.コンパイラに無視されて...
別の角度から見ると、コンパイル後に「消える」以上、最適化された可能性もあるし、宣言として処理された可能性もある.前者の場合、プログラムの論理が変わることが多いので、コンパイラはそうしない可能性が高い.もう一つの状況は可能だ.o 1が関数名である場合、この行はo 1関数という順方向宣言として解釈されます.解決策は、次のように書かれています.
B o1( (A()) );
注意本当にo 1という関数を宣言したい場合は、明らかにこのような宣言は違法です.
この方法で書かれたコードは醜いが、他に方法はない.私がこのように書いたほうがいいと言うかもしれません.
A a;
B o1(a);

このように書くのは「きれい」にすぎないが、前のコードとは全く異なるものである.まずo 1を初期化するためのオブジェクトのライフサイクルはo 1よりも長く続いた.もう一つも最も致命的なのは、ここのaは左の値です.BのA初期化構造関数がB(A&&);では、この2つのコードのo 1は、それぞれ異なるA初期化構造関数を呼び出す.