2016-12-30 18 views
0

これは部分的にはスタイルに関する質問ですが、部分的には正しい質問です。それは、書かれていることを正しいscratch_size_あるC++ - 既定のメンバ初期化子とメンバ初期化リストを混在させる - 悪い考えですか?

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_; 
}; 

まず、技術的な正しさ...:次のサンプル(埋め込まれたヘッダを含むデータのブロックを扱うクラスのストリップダウン)を提出最初に初期化され、次にheader_、次にdata_length_? (constexprアイテムはコンパイル時定数であり、初期化順序には含まれません)。どのように初期化子が宣言されているか、デフォルトメンバー初期化(int foo = 5)またはメンバー初期化子リストむしろ重要なのは、メンバーが宣言された順序だけですか?私はthis answerを見つけました。初期化順序に関するISO仕様を引用していましたが、私が収集したのは、scratch_size_がメンバー初期化リストに表示されているのに対して、デフォルトのメンバー初期化子が与えられています。他のメンバーの前にscratch_size_が宣言されていることだけが重要です。おそらく、scratch_size_が最後に宣言された場合は、header_data_length_が最初に初期化されます(望ましくない/誤って)。

スタイルに関する質問...これらの2つの初期化スタイルを混在させるのは悪いスタイルですか?私のアプローチは、メンバ初期化リスト(scratch_size_)の項目はコンストラクタに渡される引数に依存し、残りのクラスメンバは他のクラスメンバから派生します。明らかに、初期化子がコンストラクタ引数に依存する場合、にはがあり、メンバ初期化リストに入ります。私はすべてのイニシャライザをメンバー初期化リストにスローする必要がありますか? IMOは、コードを少し難しくするかもしれません。思考?

+0

私はそれが正しいと信じています。個人的にはそれほど審美的ではありませんが、他は異なるかもしれません。 –

+4

'delete [] scratch_;' –

+1

"*従来の初期化*"デフォルトのメンバー初期化子については " –

答えて

3

default member initializersの存在は、タイプのサブオブジェクトが初期化される順序については何も変更しません。 は常にとなります。

スタイルはあなた次第です。コンストラクターが多いほど、DMIを使用することでより多くの利益を得ることができます。変更しない初期化を繰り返さないためです。同時に、DMIをオーバーライドするコンストラクタの作成を開始すると、オブジェクトの初期状態を混乱させる可能性があります。重要なことは、何が起こっているのか驚かないようにすることです。

ただし、特定のケースでは、変数が多すぎるとします。配列はstd::vector<uint8_t>である必要があります。 header_ポインタを持っているのは疑わしいですが、それは防御的です(間違って初期化されていますが、C++のオブジェクトモデルを満たすためにはplacement-newを使用する必要があります)。しかし、data_length_は、必要に応じて計算することができます。

メンバーが少ないほど、初期化の方法について混乱する可能性が少なくなります。

+0

私はC言語を学んでいます+ +は、埋め込まれたCを書いた20年から来て、いくつかのC#と90年代後半にC + +の小さなビット。非常に適切な点。私はDMIと複数のコンストラクタについて理解しています。私はまた、コンストラクタのメンバ初期化子がDMIをオーバーライドすることをあなたが与えたリンクから理解しました。プレースメントの新しい意味が完全になります。これは、私がやっているようにポインタを悪用することなく、オーバーライドを行う言語上の正しい手段です。そして再:あまりにも多くの変数、私はおそらく時期尚早な最適化の有罪です。 1行の関数はあまりパフォーマンスペナルティではありません。助けてくれてありがとう。 –

-1

constやnon-constのどちらがイニシャライザリストで初期化されているかにかかわらず、すべてのフォーラムでクラスメンバにアドバイスされています。あなたの場合、それは問題ではないかもしれませんが、クラスが拡張のために使用されたとき、それは問題を与えることができます。

関連する問題