2013-05-21 6 views
5

とconstの配列を含む構造体を初期化します。は、私はC++ 11と協力し、以下の構造体を含むクラスを持つ初期化子リスト

struct Settings{ 
    const std::string name; 

    const std::string* A; 
    const size_t a; 
}; 

class X { 
    static const Settings s; 
    //More stuff 
}; 

私はこの

のようにそれを定義したい .cppファイルで
X::s = {"MyName", {"one","two","three"}, 3}; 

しかし、これは動作しません。しかし、中間変数を使用して動作します

const std::string inter[] = {"one","two","three"}; 
X::s = {"MyName", inter, 3}; 

中間変数なしで行う方法はありますか?

+3

あなたの構造体*にはconst配列は含まれていません。これは、const文字列へのポインタを含んでいます。そのことを念頭に置いて、なぜ "中間変数"が必要かを理解することは容易です。 – juanchopanza

+0

@juanchopanza:まあ、 'A'がconst配列(の始まり)を指し示したいと思っています。それは 'const std :: string'へのポインタでもありますが、私が望むものではありません。しかし、たぶん私はあなたが指しているものを得られないかもしれません。 – Haatschii

+1

@Haatschii:配列とポインタが同じであるという考えで配列が崩壊するという事実を混乱させています。言語セマンティクスの面では、配列はポインタではありません。同様に、初期化子リストは配列ではありません。コンパイラはそのようなリストを持つ配列を初期化することができますし、配列をポインタに崩壊させることはできますが、あなたの例ではリストを配列に変換してそれをポインタに壊すことはわかりません。したがって、ポインタに代入する前に、イニシャライザリストを連続した配列に変換するために、仲介が必要です。 –

答えて

5

ポインタを値のリストから初期化することはできません。あなたが代わりにstd::vectorを使用することもできます。

#include <vector> 

struct Settings{ 
    const std::string name; 
    const std::vector<std::string> A; 
//  ^^^^^^^^^^^^^^^^^^^^^^^^ 
    const size_t a; 
}; 

を次に、書くことができます:ここで

class X { 
    static const Settings s; 
    //More stuff 
}; 

const Settings X::s = {"MyName", {"one","two","three"}, 3}; 

live exampleです。

As suggested by Praetorian in the comments、あなたが明示的にコンテナのサイズを指定するため、およびサイズは、実行時に変更する必要がない場合、それが許容される場合、std::arraystd::vectorを交換することがあります。

#include <array> 

struct Settings{ 
    const std::string name; 
    const std::array<std::string, 3> A; 
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^ 
    const size_t a; 
}; 

ここにはlive exampleがあります。

+1

なぜベクトルを使って違いがあるのか​​説明できますか? – taocp

+1

@taocp:ポインタを値のリストで初期化することはできません。あなたが望むのは、イニシャライザリスト –

+3

から初期化できるものです。サイズ変更が不要な場合は、 'std :: array 'となります。 – Praetorian

5

これは、文字列自体ではなく、文字列の配列へのポインタを格納するためです。そのため、あなたはどこかに指すべき文字列の配列が必要です。あなたが持っているのは、文字配列へのポインタを含むブレースイニシャライザーです。

文字列自体を格納する場合(たとえば、vector<string>)、最初のバージョンが機能します。

関連する問題