20

I am working on editing some old C++ code that uses global arrays defined like so:

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};

I want to make all of these arrays private members of the Robot class defined below. However, the C++ compiler does not let me initialize data members when I declare them.

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
}

I want to initialize the elements of these six arrays in the Robot() constructor. Is there any way to do this other than assigning each element one by one?

Michael Hornfeck
  • 1,242
  • 1
  • 16
  • 33
  • Easiest would be to make them static members, because they were globals before, however, this is not as in the original question. – stefaanv Apr 13 '11 at 03:09

9 Answers9

23

If your requirement really permits then you can make these 5 arrays as static data members of your class and initialize them while defining in .cpp file like below:

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

If that is not possible then, declare this arrays as usual with different name and use memcpy() for data members inside your constructor.

Edit: For non static members, below template style can be used (for any type like int). For changing the size, simply overload number of elements likewise:

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

The array initialization has now become trivial:

class Robot
{
   private:
       int posLShd[5];
       ...
   public:
       Robot() : posLShd{0, 1, 2, 3, 4}, ...
       {}
};
iammilind
  • 68,093
  • 33
  • 169
  • 336
  • 2
    The best part of this answer is at the end, as is so often the case with edited vintage answers. – Wyck Feb 17 '22 at 16:57
12

you can either make it static, or use the new initialisation introduced in 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};
andreabedini
  • 1,295
  • 1
  • 13
  • 20
5

To throw one other approach into the mix (and one that doesn't tell you to make the array data members static as most of the other answers do – I assume you know whether or not they should be static), here's the zero-overhead approach I use: Make static member functions and have them return std::array<> (or boost::array<> if your compiler is too old to come with a std:: or std::tr1:: implementation):

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())
{ }
ildjarn
  • 62,044
  • 9
  • 127
  • 211
  • Is this really 0 overhead? It looks like the static functions will have to copy the entire array each time, rather than initializing the array elements in place. Maybe I misunderstand initialization in C++? – weberc2 Jun 23 '14 at 17:34
  • 2
    @weberc2 : [NRVO](http://en.wikipedia.org/wiki/Return_value_optimization) makes this a non-issue in practice. – ildjarn Jun 23 '14 at 18:45
3

Is there any way to do this other than assigning each element one by one?

If you wish to fill all the elements of array with some default values, std::fill can be used.

#include <algorithm>

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

    // Similarly work on with other arrays too.
}

If each element of the array needs to be filled with a different value, then assigning value at each index is the only option.

Mahesh
  • 34,573
  • 20
  • 89
  • 115
1

Leave the globals in the code and then initialize the local arrays with memcpy(), copying the contents of the global arrays to the local ones.

Antti Huima
  • 25,136
  • 3
  • 52
  • 71
1

This is only slightly related to the present question, but is a special case that fully addresses a duplicate.

Zero initialization is a special case for arrays in C++ language. If the initialization list is shorter than the array, the remaining elements are zero initialized. For example, the requirement for the duplicate question was to zero initialize all members of the class including all elements of the last array in constructor:

class myprogram {
public:
    myprogram ();
private:
    double aa,bb,cc;
    double G_[2000];
};

This is enough for the constructor definition:

myprogram::myprogram():aa(0.0),bb(0.0),cc(0.0), G_{0.} {}

because the first element of G_ is explicitely initialized to the value 0. and all the other elements are zero initialized.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
0

Am I missing something here? The code below works. Simply declare the members, and initialize right away.

#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;
  }
}
daparic
  • 3,794
  • 2
  • 36
  • 38
  • It does not work and compiler error is: `a brace-enclosed initializer is not allowed here ...`. Even if it worked it is not very useful. I would not put real/scific data into a header file, where the class has been defined. I would also be hesitant to specify a number of elements by putting in data only. Doing that in constructor initialization list is something different - you can have a variety of data sets for initialization which you can choose run time, allowing rich settings management for instance. – OpalApps Apr 04 '19 at 13:23
0
// 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};
CyberDem0n
  • 14,545
  • 1
  • 34
  • 24
0

Not really, although I agree with stefaanv's comment - if they were global previously, making them static would get you the "easy assignment", and they seem as though they may be const static at a glance.

If these values are something you change occasionally, you might consider reading them in from an external file on class creation, such that you can avoid recompiles.

You also might consider using std::vector instead of the fixed arrays for some of the features it provides.

holtavolt
  • 4,378
  • 1
  • 26
  • 40