これは、スタイルの問題でもあり、正しさの問題でもあります。次のサンプル (埋め込みヘッダーを含むデータのブロックを処理するクラスのストリップダウン) を送信します。
class Foo {
public:
Foo(size_t size)
: scratch_(new uint8_t[header_length_ + size]),
size_(header_length_ + size) {
}
~Foo() {
delete[] scratch_;
}
Foo(const Foo&) = delete; // Effective C++
void operator=(const Foo&) = delete; // Effective C++
protected:
struct Header {
uint32_t a, b, c, d;
};
uint8_t * const scratch_;
size_t const size_;
Header * const header_ = reinterpret_cast<Header *>(scratch_);
static constexpr size_t header_length_ = sizeof(Header);
static constexpr size_t data_offset_ = header_length_;
size_t const data_length_ = size_ - data_offset_;
};
まず、技術的な正しさ... 書かれているとおりで、最初に初期化scratch_
され、次に? (アイテムはコンパイル時のリテラル定数であり、初期化順序を考慮しません。)また、初期化子の宣言方法が、デフォルトのメンバー初期化( )またはメンバー初期化子リストであっても、初期化順序に影響を与えないことも正しいですか?しかし、むしろ、メンバーが宣言される順序だけが重要なのでしょうか? 初期化順序に関するISO仕様を引用して、この回答を見つけました。私が集めたのは、それは重要ではないということです。size_
header_
data_length_
constexpr
int foo = 5
scratch_
size_
デフォルトのメンバー初期化子が与えられている他のメンバーと比較して、メンバー初期化リストに表示されます。scratch_
およびsize_
が他のメンバーの前に宣言されていることだけが重要です。おそらくscratch_
andsize_
が最後に宣言された場合、 header_
anddata_length_
は (望ましくない/間違って) 最初に初期化されます。
スタイルの質問...これら 2 つの初期化スタイルを混在させるのは悪いスタイルですか? 私のアプローチは、メンバー初期化リスト ( scratch_
、size_
) の項目はコンストラクターに渡される引数に依存し、残りのクラス メンバーは他のクラス メンバーから派生するというものです。明らかに、イニシャライザがコンストラクタ引数に依存している場合は、メンバ初期化リストに入る必要があります。すべての初期化子をメンバー初期化リストに入れ、デフォルトのメンバー初期化子を放棄する必要がありますか? IMO、それにより、コードを追跡するのが少し難しくなる可能性があります。考え?