3

これは、スタイルの問題でもあり、正しさの問題でもあります。次のサンプル (埋め込みヘッダーを含むデータのブロックを処理するクラスのストリップダウン) を送信します。

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_constexprint foo = 5scratch_size_デフォルトのメンバー初期化子が与えられている他のメンバーと比較して、メンバー初期化リストに表示されます。scratch_およびsize_が他のメンバーの前に宣言されていることだけが重要です。おそらくscratch_andsize_が最後に宣言された場合、 header_anddata_length_は (望ましくない/間違って) 最初に初期化されます。

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

4

2 に答える 2

-1

const か non-const かに関係なく、すべてのフォーラム、クラス メンバーで、イニシャライザ リストで初期化することをお勧めします。あなたの場合は問題にならないかもしれませんが、クラスが拡張に使用されると問題が発生する可能性があります。

于 2016-12-30T06:05:44.167 に答える