次の3つを検討してくださいstruct
。
class blub {
int i;
char c;
blub(const blub&) {}
};
class blob {
char s;
blob(const blob&) {}
};
struct bla {
blub b0;
blob b1;
};
int
が4バイトである一般的なプラットフォームでは、サイズ、配置、およびパディングの合計1は次のとおりです。
struct size alignment padding
-------- ------ ----------- ---------
blub 8 4 3
blob 1 1 0
bla 12 4 6
サイズ1 は原則としてのパディングに「適合」することができますが、blub
とblob
メンバーのストレージ間に重複はありません。blob
blub
C ++ 20ではno_unique_address
属性が導入され、隣接する空のメンバーが同じアドレスを共有できるようになりました。また、1つのメンバーのパディングを使用して別のメンバーを格納するという上記のシナリオを明示的に許可します。cppreferenceから(私の強調):
このデータメンバーは、そのクラスの他のすべての非静的データメンバーと異なるアドレスを持つ必要がないことを示します。これは、メンバーが空の型(たとえば、ステートレスアロケーター)を持っている場合、コンパイラーがそれを最適化して、空のベースであるかのようにスペースを占有しないことを意味します。メンバーが空でない場合、その中のテールパディングも他のデータメンバーを格納するために再利用できます。
実際、この属性をで使用するblub b0
と、サイズはにbla
下がります8
。そのため、blob
は実際blub
にgodboltで見られるようにに格納されます。
最後に、私は私の質問に行きます:
標準ではどのテキストが(C ++ 11からC ++ 20まで)no_unique_address
簡単にコピーできないオブジェクトに対して、なしでこの重複を防ぎますか?
TCオブジェクトのstd::memcpy
場合、メンバーサブオブジェクトを含む、あるオブジェクトから別のオブジェクトへの移動が許可されており、ストレージがオーバーラップしている場合、これは壊れます(ストレージのすべてまたは一部のため)。隣接するメンバーは上書きされます)2。
1パディングは、構造サイズとそのすべての構成メンバーのサイズの差として再帰的に単純に計算されます。
2作るために:私はコピーコンストラクタが定義されている理由はここにあるblub
とblob
ない自明コピー可能。