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


98
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. やりたいことを行うにはどうすればよいですか(つまり、コンストラクターで配列を初期化します(本体の要素を割り当てません))。それも可能ですか?
  2. C ++ 03標準は、ctor初期化子での集約(配列を含む)の初期化に関して特別なことを言っていますか?または、上記のコードの無効性は他のいくつかのルールの当然の結果ですか?
  3. C ++ 0x初期化リストは問題を解決しますか?

PS私がよく知っているベクトル、boost :: array、および配列に対するその優位性については言及しないでください。


コンストラクターを提供するブースト固定サイズ配列の存在も知っていますか?
2010年

2
@Benoît:私はそうです。しかし、私は単純な配列について知る必要があります:)
Armen Tsirunyan

回答:


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

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

C ++ 03標準は、ctor初期化子での集約(配列を含む)の初期化に関して特別なことを言っていますか?または、上記のコードの無効性は他のいくつかのルールの当然の結果ですか?

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

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

詳細については、このGCC PRを参照してください。

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

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

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

私が書いたときに私はこれに偶然出会いました:char * const foo[6];クラスメンバー。C ++ 11でコンパイルするに、初期化子が必要です。
JATothrim 2018

32

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

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

現在のコードのC ++ 98の回避策は、配列をaでラップし、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}};

0xにはどのような制限がありますか?

@Roger:「初期化を集約...はctor初期化子に適合しません」。C ++ 0xドラフトN3126をチェックするだけで、§12.5.2/ 1のmem-initializerの構文には、braced -init-listの使用が含まれます
乾杯とhth。-アルフ

6
私の文の最初の2語はC ++ 03の場合、...

8

回避策:

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()) {}
};

3
  1. いいえ、残念ながら。
  2. 文法では許可されていないので、希望どおりに操作することはできません(以下を参照)。使用できるのはctorのような初期化のみであり、ご存知のように、配列内の各項目の初期化には使用できません。
  3. 彼らは多くの有用な方法で全面的に初期化を一般化しているので、私はそう信じています。しかし、詳細はわかりません。

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

T var = {...};

2

いかがですか

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

g ++ 4.8で問題なくコンパイル


これは標準ですか?関連条項を引用していただけますか?
Armen Tsirunyan、2014年

2
Visual C ++ではコンパイルしません。
sergiol

-2

コンストラクターでintの配列を初期化したいですか?静的配列を指します。

class C 
{
public:
    int *cArray;

};

C::C {
    static int c_init[]{1,2,3};
    cArray = c_init;
}

2
これは悪い考えです。その配列を変更すると、そのクラスのすべてのインスタンスで変更されるためです。
死者
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.