web-dev-qa-db-ja.com

C ++非静的メンバー配列の初期化

私は次のように定義されたグローバル配列を使用するいくつかの古いC++コードの編集に取り組んでいます:

int posLShd[5] = {250, 330, 512, 600, 680};
int posLArm[5] = {760, 635, 512, 320, 265};
int posRShd[5] = {765, 610, 512, 440, 380};
int posRArm[5] = {260, 385, 512, 690, 750};
int posNeck[5] = {615, 565, 512, 465, 415};
int posHead[5] = {655, 565, 512, 420, 370};

これらの配列をすべて、以下に定義するRobotクラスのプライベートメンバーにしたいと考えています。ただし、C++コンパイラでは、データメンバーを宣言するときにデータメンバーを初期化できません。

class Robot
{
   private:
       int posLShd[5];
       int posLArm[5];
       int posRShd[5];
       int posRArm[5];
       int posNeck[5];
       int posHead[5];
   public:
       Robot();
       ~Robot();
};

Robot::Robot()
{
   // initialize arrays
}

Robot()コンストラクターでこれら6つの配列の要素を初期化したい。各要素を1つずつ割り当てる以外にこれを行う方法はありますか?

15

要件が本当に許せば、これらの5つの配列をクラスのstaticデータメンバーとして作成し、以下のように.cppファイルで定義しながらそれらを初期化できます。

_class Robot
{
  static int posLShd[5];
  //...
};
int Robot::posLShd[5] = {250, 330, 512, 600, 680}; // in .cpp file
_

それが不可能な場合は、通常どおりこの配列を別の名前で宣言し、コンストラクター内のデータメンバーにmemcpy()を使用します。

編集:非静的メンバーの場合、以下のtemplateスタイルを使用できます(intなどの任意のタイプ)。サイズを変更するには、同様に要素の数をオーバーロードします。

_template<size_t SIZE, typename T, T _0, T _1, T _2, T _3, T _4>
struct Array
{
  Array (T (&a)[SIZE])
  {
    a[0] = _0;
    a[1] = _1;
    a[2] = _2;
    a[3] = _3;
    a[4] = _4;
  }
};

struct Robot
{
  int posLShd[5];
  int posLArm[5];
  Robot()
  {
    Array<5,int,250,330,512,600,680> o1(posLShd);
    Array<5,int,760,635,512,320,265> o2(posLArm);
  }
};
_

C++ 11

アレイの初期化は簡単になりました。

_class Robot
{
   private:
       int posLShd[5];
       ...
   public:
       Robot() : posLShd{0, 1, 2, 3, 4}, ...
       {}
};
_
15
iammilind

あなたはそれを静的にするか、C++ 0xで導入された新しい初期化を使用することができます

class Robot
{
private:
  int posLShd[5];
  static int posLArm[5];
  // ...
public:
  Robot() :
    posLShd{250, 330, 512, 600, 680} // only C++0x                                                                                     
  {}

  ~Robot();
};

int Robot::posLArm[5] = {760, 635, 512, 320, 265};
12
andreabedini

もう1つのアプローチをミックスに投入するには(そしてしないアプローチは、配列データメンバーをstaticにするように指示します。他の答えはそうです–私はyouがそれらがstaticであるべきかどうかを知っていると思います、これが私が使用するゼロオーバーヘッドアプローチです: staticメンバー関数を作成し、std::array<>(または boost::array<> が古すぎてstd::またはstd::tr1::実装):

class Robot
{
    static std::array<int, 5> posLShd_impl() { std::array<int, 5> x = {{ 250, 330, 512, 600, 680 }}; return x; }
    static std::array<int, 5> posLArm_impl() { std::array<int, 5> x = {{ 760, 635, 512, 320, 265 }}; return x; }
    static std::array<int, 5> posRShd_impl() { std::array<int, 5> x = {{ 765, 610, 512, 440, 380 }}; return x; }
    static std::array<int, 5> posRArm_impl() { std::array<int, 5> x = {{ 260, 385, 512, 690, 750 }}; return x; }
    static std::array<int, 5> posNeck_impl() { std::array<int, 5> x = {{ 615, 565, 512, 465, 415 }}; return x; }
    static std::array<int, 5> posHead_impl() { std::array<int, 5> x = {{ 655, 565, 512, 420, 370 }}; return x; }

    std::array<int, 5> posLShd;
    std::array<int, 5> posLArm;
    std::array<int, 5> posRShd;
    std::array<int, 5> posRArm;
    std::array<int, 5> posNeck;
    std::array<int, 5> posHead;
public:
    Robot();
};

Robot::Robot()
  : posLShd(posLShd_impl()),
    posLArm(posLArm_impl()),
    posRAhd(posRAhd_impl()),
    posRArm(posRArm_impl()),
    posNeck(posNeck_impl()),
    posHead(posHead_impl())
{ }
4
ildjarn

各要素を1つずつ割り当てる以外にこれを行う方法はありますか?

配列のすべての要素をいくつかのデフォルト値で埋めたい場合は、std::fill に使える。

#include <algorithm>

// ...
Robot::Robot()
{
    std::fill(posLShd, posLShd+5, 13 ) ; // 13 as the default value

    // Similarly work on with other arrays too.
}

配列の各要素に異なる値を入力する必要がある場合は、各インデックスに値を割り当てることが唯一のオプションです。

3
Mahesh

コードにグローバルを残してから、memcpy()を使用してローカル配列を初期化し、グローバル配列の内容をローカル配列にコピーします。

1
Antti Huima

ここで何か不足していますか?以下のコードは機能します。単にメンバーを宣言し、すぐに初期化します。

#include <iostream>

class Robot {
  public:
  int posLShd[5] = {250, 330, 512, 600, 680};
  int posLArm[5] = {760, 635, 512, 320, 265};
  int posRShd[5] = {765, 610, 512, 440, 380};
  int posRArm[5] = {260, 385, 512, 690, 750};
  int posNeck[5] = {615, 565, 512, 465, 415};
  int posHead[5] = {655, 565, 512, 420, 370};
  public:
    Robot() {}
    ~Robot() {}
};

int main () {
  Robot obj;
  for (int i = 0;i < 5;i++) {
    std::cout << obj.posRArm[i] << std::endl;
  }
}
0
typelogic
// class definition with incomplete static member could be in a header file
Class Robot {
    static const int posLShd[5];
....
// this needs to be placed in a single translation unit only
const int Robot::posLShd[5] = {250, 330, 512, 600, 680};
0
CyberDem0n

実際にはそうではありませんが、stefaanvのコメントに同意します。以前はグローバルだった場合、静的にすると「簡単な割り当て」が得られ、一見すると静的であるように見えます。

これらの値が時々変更されるものである場合は、再コンパイルを回避できるように、クラスの作成時に外部ファイルからそれらを読み込むことを検討してください。

また、提供される機能の一部に、固定配列の代わりにstd :: vectorを使用することを検討することもできます。

0
holtavolt