0

使用したい構造体を以下に定義します。(私は使用していますnamespace std):

struct body {string name; float m; vector< float > p; vector< float > v;};

これはコンパイルされますが、後で実行時にセグメンテーション違反が発生します。これは、ベクトルのサイズが定義されていないためです (3 つのコンポーネントが必要です)。

ベクトル コンストラクターを使用してみましたvector x(3,0)が、これはコンパイルされません。私は得る:

glib.h(5): error: expected a type specifier
  struct body {string name; float m; vector<float> p (3,0); vector<float> v(3,0);};
                                                      ^

glib.h(5): error: expected a type specifier
  struct body {string name; float m; vector<float> p (3,0); vector<float> v(3,0);};
                                                        ^

glib.h(5): error: expected a type specifier
  struct body {string name; float m; vector<float> p (3,0); vector<float> v(3,0);};
                                                                            ^

glib.h(5): error: expected a type specifier
  struct body {string name; float m; vector<float> p (3,0); vector<float> v(3,0);};

基本的に、構造体を定義するときに 3 つの要素のベクトルにスペースを割り当てる必要がありますが、これを行う方法がわかりません。私は C++ の初心者で、多くの調査を行いましたが、答えが見つかりません。私が得ることができる助けをありがとう。

4

3 に答える 3

1

コンストラクター内でベクター コンストラクターを呼び出します。

struct body {
    string name; 
    float m; 
    vector< float > p; 
    vector< float > v;

    body(): p(3,0), v(3,0) {}
};
于 2013-10-28T19:23:18.950 に答える
1

のコンストラクターでベクトルのサイズを指定できますbody

struct body {
    string name; 
    float m; 
    vector< float > p; 
    vector< float > v;

     body() : p(3), v(3) {}
};

C++11 では、コンストラクター引数を「その場で」指定できるため、次のようになります。

struct body {
    string name; 
    float m; 
    vector< float > p{3}; 
    vector< float > v{3};
};

...許可されていますが、コンパイラがそれをサポートしていないようです (更新の時期でしょうか?)

編集:少しチェックすると、2番目のコードが与えられたときにすべてのコンパイラが正しいコンストラクタを選択するとは限らないようです。たとえば、上記のコードでは、VC++ は 3 つの 0 を含むベクトルを返しますが、g++ は単一の値 3 を含むベクトルを返します。つまり、g++ は初期化子リストを取るオーバーロードを使用していますが、VC++ はパラメータを 1 つ取ります。

価値が何であれ、g++ はこれを正しく行っており、VC++ は正しくないように見えます1 コンパイラ ベンダーが協力するまで)。


  1. 具体的な文言は $13.3.1.7 にあります。

    • 最初は、候補関数はクラス T の初期化子リスト コンストラクター (8.5.4) であり、引数リストは単一の引数としての初期化子リストで構成されます。
    • 実行可能な初期化子リスト コンストラクターが見つからない場合、オーバーロードの解決が再度実行されます。ここで、候補関数はすべてクラス T のコンストラクターであり、引数リストは初期化子リストの要素で構成されます。

std::vector実行可能かどうかの問題を残して、初期化リストのコンストラクターを持っています。それは、 a3へのfloat変換が「縮小変換」であるかどうかの問題に帰着します。この場合、答えはノーです。そうではありません。公式の文言は次のとおりです (§8.5.4/7):

縮小変換は暗黙の変換です

[ ... ]

ソースが定数式であり、変換後の実際の値がターゲットの型に適合し、元の型に変換されたときに元の値が生成される場合を除き、整数型またはスコープなし列挙型から浮動小数点型へ。

3したがって、値で定数式を使用しており、floatその値を保持できることが保証されており、3それを に戻すと結果として生成されるためint、これは縮小変換ではありません。つまり、initializer-list コンストラクターが実行可能であるため、これを選択する必要があります。

理論的には、インプレース初期化を行いたい場合は、おそらく次を使用する必要があります。

std::vector<float> p{0, 0, 0};

...しかし、MS VC++ はこれを拒否し、移植性を気にする場合は一般的にこれを避けたいという以前のアドバイスを強化します。

于 2013-10-28T19:24:14.777 に答える
1

いくつかのオプションがあります:

1) コンストラクターを追加して、ベクターをサイズ 3 に初期化します。

struct body 
{
  body() : p(3), v(3) {}
  string name; 
  float m; 
  vector< float > p; 
  vector< float > v;
};

2) 宣言の時点で変数を初期化する (C++11)

struct body 
{
  string name; 
  float m; 
  vector< float > p = vector<float>(3); 
  vector< float > v = vector<float>(3);
};

3)std::array<float, 3>ベクトルの代わりに使用

struct body 
{
  body() : p(3), v(3) {}
  string name; 
  float m; 
  std::array<float, 3> p; 
  std::array<float, 3> v;
};

3) ブレースの初期化を使用して、構造体をインスタンス化します。

body b1 {"hello", 3.14, vector(3,0), vector(3,0) };
于 2013-10-28T19:24:49.747 に答える