3

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[];
};
14
  • What is this code attempting to do? Commented Nov 9, 2011 at 20:48
  • 2
    I'm a bit surprised that that's even valid syntax; never knew you could write the horrid T ar[] outside of a function parameter list. Commented Nov 9, 2011 at 20:52
  • 2
    @TomalakGeret'kal: If I recall, it's a common extension to allow it as the last member of a type, so you can allocate with malloc(sizeof(A)+3) and pretend the b is an array of B[4]. Commented Nov 9, 2011 at 20:54
  • @Mooing: Yuk!??! Anyway, no wonder I can't find it in the standards. It's strictly an implementation extension, then? Commented Nov 9, 2011 at 20:55
  • 1
    @avakar: As far as I know it's a C99 feature. It isn't in any version of C++, though. Commented Nov 9, 2011 at 21:08

4 Answers 4

4

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;
};
Sign up to request clarification or add additional context in comments.

3 Comments

B *b is not the same as B b[] in this context.
Would be +1 for an excellent explanation, but for the factually incorrect statements in the first paragraph.
@avakar, @Rob: Learned something new today! My answer should be complete now. `
2

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.

Comments

1

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).

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.