user695652
user695652

Reputation: 4275

Array in Constructor

What happens in the following code?

I guess it doesn't work since I get a segmentation fault if I want to add something to the b array, but what exactly did I do here?

Is there no way of specifying the size of an array inside the constructor?

class A {
  public:
   A() {
      b[3];
   }
  private:
    B b[];
};

Upvotes: 3

Views: 173

Answers (4)

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385108

B b[] here is a "flexible array member", a non-standard extension in your compiler (taken from C99) that allows you to declare an unbounded array as the last member in a type. It's only of use when allocating your object the old-fashioned C way (when you pad your argument to malloc to make space for the array), and ought to be avoided. In this case, you haven't allocated any extra memory for the array, so in your constructor body when you're trying to access something that occurs 3 'elements' past this nothingness, you're invoking UB. I'll ignore the extension for the rest of my answer, as it really has no place in C++ code.

Is there no way of specifying the size of an array inside the constructor?

No, there isn't.

Array bounds must be known at compile-time, so there is no case where you know more in your ctor body than you do in the class definition; you are required to write the dimension in the member's declaration itself:

class A {
    B b[3];
};

If the dimension is a run-time quantity in your program, you'll need to instead store a pointer and, in your constructor, point it at a dynamic block of memory:

class A {
  public:
   A() : b(new B[3]) {}
  ~A() { delete[] b; }
  private:
    B* b;   // same as `B b[]`! but far clearer
};

Instead, though, I suggest a std::vector:

class A {
  public:
   A() : b(3) {}
  private:
    std::vector<B> b;
};

Upvotes: 4

celtschk
celtschk

Reputation: 19721

C++ doesn't support any types with size determined at runtime. Therefore you have only the options to determine the array size at compile time (possible through a non-type template parameter) or move the array out of the object by making b a pointer and allocating memory for it with new (or, better, let the standard library do that for you by using a vector).

Upvotes: 1

littleadv
littleadv

Reputation: 20262

Yes. Using operator new: b = new B[3];. Declare b as B *b for that. Of course, you need to delete[] it in the destructor.

But a better way would be using std::vector instead of the array, and then you don't need to worry about preallocating memory.

Upvotes: 2

misberner
misberner

Reputation: 3678

This is not possible - what would you expect sizeof(A) to evaluate to?! If you really need such functionality, use dynamic allocation, i.e. a private member variable B *b, b(new B[3]) in the constructors initializer list, and delete[] b; in the destructor.

Upvotes: 0

Related Questions