web-dev-qa-db-ja.com

コンストラクター初期化子でメンバー配列を初期化する

class C 
{
public:
 C() : arr({1,2,3}) //doesn't compile
{}
    /*
    C() : arr{1,2,3} //doesn't compile either
{}
    */
private:
 int arr[3];
};

その理由は、配列が=構文でのみ初期化できるからだと信じています。

int arr[3] = {1,3,4};

ご質問

  1. 私がやりたいことをどのように行うことができますか(つまり、initializeコンストラクター内の配列(本体内の要素を割り当てない))。それも可能ですか?
  2. C++ 03標準では、ctorイニシャライザーでの集計(配列を含む)の初期化について特別なことを述べていますか?または、上記のコードの無効性は、他のいくつかのルールの結果ですか?
  3. C++ 0x初期化リストは問題を解決しますか?

P.S。ベクトル、boost :: arrays、および配列に対するそれらの優位性については言及しないでください。

89
Armen Tsirunyan
  1. やりたいことを実行するにはどうすればよいですか(つまり、コンストラクターで配列を初期化します(本体に要素を割り当てません))。それも可能ですか?

はい。配列を含む構造体を使用しています。あなたはすでにそれについて知っていると言いますが、それから私は質問を理解しません。そのようにして、本体での割り当てなしで、コンストラクターで配列を初期化しますdo。これはboost::arrayが行うことです。

C++ 03標準では、ctorイニシャライザーでの集計(配列を含む)の初期化について特別なことを述べていますか?または、上記のコードの無効性は、他のいくつかの規則の結果ですか?

Mem-initializerは直接初期化を使用します。そして、第8条の規則は、この種のことを禁止しています。次のケースについては正確にはわかりませんが、一部のコンパイラでは許可されています。

struct A {
  char foo[6];
  A():foo("hello") { } /* valid? */
};

詳細については this GCC PR をご覧ください。

C++ 0x初期化リストは問題を解決しますか?

はい、彼らがやります。しかし、構文は無効だと思います。リストの初期化を開始するには、中括弧を直接使用する必要があります

struct A {
  int foo[3];
  A():foo{1, 2, 3} { }
  A():foo({1, 2, 3}) { } /* invalid */
};

C++ 98は、配列のゼロ化(または非POD要素、値の初期化)以外の直接構文を提供しません。そのためにC(): arr() {}と書くだけです。

Roger PateがC++ 0x集計の初期化の制限の疑いについて間違っているのは確かですが、私はそれを調べたりチェックアウトしたりするのが面倒なので、それは問題ではありませんか? EDIT:ロジャーは「C++ 03」について話していましたが、「C++ 0x」と誤解していました。ごめんなさい、ロジャー。 ☺

現在のコードのC++ 98の回避策は、配列をstructでラップし、その型の静的定数から初期化することです。とにかくデータはどこかに存在しなければなりません。袖口から次のようになります。

class C 
{
public:
    C() : arr( arrData ) {}

private:
     struct Arr{ int elem[3]; };
     Arr arr;
     static Arr const arrData;
};

C::Arr const C::arrData = {{1, 2, 3}};
28

回避策:

template<class T, size_t N>
struct simple_array { // like std::array in C++0x
   T arr[N];
};


class C : private simple_array<int, 3> 
{
      static simple_array<int, 3> myarr() {
           simple_array<int, 3> arr = {1,2,3};
           return arr;
      }
public:
      C() : simple_array<int, 3>(myarr()) {}
};
6
Alexey Malistov
  1. いいえ、残念ながら。
  2. 文法で許可されていないので、望みどおりにはできません(以下で詳しく説明します)。使用できるのはctorのような初期化のみです。ご存知のように、配列内の各アイテムの初期化には使用できません。
  3. 私はそう信じています、彼らは多くの有用な方法で全面的に初期化を一般化しているからです。しかし、私は詳細がわかりません。

C++ 03では、集約の初期化は以下のような構文でのみ適用されます。これは別個のステートメントである必要があり、ctor初期化子には適合しません。

T var = {...};
3
Roger Pate

どう?

...
  C() : arr{ {1,2,3} }
{}
...

G ++ 4.8で正常にコンパイルします。

1
eold