Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any workarounds for non-static member array initialization?

Tags:

c++

In C++, it's not possible to initialize array members in the initialization list, thus member objects should have default constructors and they should be properly initialized in the constructor. Is there any (reasonable) workaround for this apart from not using arrays?

[Anything that can be initialized using only the initialization list is in our application far preferable to using the constructor, as that data can be allocated and initialized by the compiler and linker, and every CPU clock cycle counts, even before main. However, it is not always possible to have a default constructor for every class, and besides, reinitializing the data again in the constructor rather defeats the purpose anyway.]

E.g. I'd like to have something like this (but this one doesn't work):

class OtherClass {
private:
    int data;
public:
    OtherClass(int i) : data(i) {}; // No default constructor!
};

class Foo {
private:
    OtherClass inst[3]; // Array size fixed and known ahead of time.
public:
    Foo(...)
        : inst[0](0), inst[1](1), inst[2](2)
        {};
};

The only workaround I'm aware of is the non-array one:

class Foo {
private:
    OtherClass inst0;
    OtherClass inst1;
    OtherClass inst2;
    OtherClass *inst[3];
public:
    Foo(...)
        : inst0(0), inst1(1), inst2(2) {
        inst[0]=&inst0;
        inst[1]=&inst1;
        inst[2]=&inst2;
    };
};

Edit: It should be stressed that OtherClass has no default constructor, and that it is very desirable to have the linker be able to allocate any memory needed (one or more static instances of Foo will be created), using the heap is essentially verboten. I've updated the examples above to highlight the first point.

like image 263
Tomi Junnila Avatar asked Sep 23 '08 09:09

Tomi Junnila


People also ask

Where do you initialize a non-static class member that is a reference?

Member initialization Non-static data members may be initialized in one of two ways: 1) In the member initializer list of the constructor.

Are arrays automatically initialized to 0?

An array may be partially initialized, by providing fewer data items than the size of the array. The remaining array elements will be automatically initialized to zero.

Do arrays need to be initialised?

You do not need to initialize all elements in an array. If an array is partially initialized, elements that are not initialized receive the value 0 of the appropriate type. The same applies to elements of arrays with static storage duration.

Can we initialize data members in a class C++?

In C++, class variables are initialized in the same order as they appear in the class declaration. Consider the below code. The program prints correct value of x, but some garbage value for y, because y is initialized before x as it appears before in the class declaration.


1 Answers

One possible workaround is to avoid the compiler calling the OtherClass constructor at all, and to call it on your own using placement new to initialize it whichever way you need. Example:

  class Foo
  {
  private:
    char inst[3*sizeof(OtherClass)]; // Array size fixed. OtherClass has no default ctor.

    // use Inst to access, not inst
    OtherClass &Inst(int i) {return (OtherClass *)inst+i;}
    const OtherClass &Inst(int i) const {return (const OtherClass *)inst+i;}
  public:
    Foo(...)
    {
      new (Inst(0)) OtherClass(...);
      new (Inst(1)) OtherClass(...);
      new (Inst(2)) OtherClass(...);
    }
    ~Foo()
    {
      Inst(0)->~OtherClass();
      Inst(1)->~OtherClass();
      Inst(2)->~OtherClass();
    }
  };

To cater for possible alignment requirements of the OtherClass, you may need to use __declspec(align(x)) if working in VisualC++, or to use a type other than char like:

Type inst[3*(sizeof(OtherClass)+sizeof(Type)-1)/sizeof(Type)];

... where Type is int, double, long long, or whatever describes the alignment requirements.

like image 185
Suma Avatar answered Oct 11 '22 22:10

Suma