12

I was wondering if it is possible to declare an array (size not known at this time), as a private member of a class and later set the size in the constructor of the class. For example:

class Test {
int a[];
public:
Test(int size);
};

Test::Test(int size) {
a[size];   // this is wrong, but what can i do here?
}

Is this possible or should I use dynamic arrays? Thanks!

7 Answers 7

17

Short Answer: No (The size of an array is defined at compile time only)
Long Answer:

You can use a vector to achieve the same result:

class Test
{
    std::vector<int> a;
    public:
        Test(std::size_t size):
            a(size)
        {}
};
Sign up to request clarification or add additional context in comments.

5 Comments

I wish people would add comments when marking down answers. At least you're back to 0
Haters love to hate anonymously. Hate the haters! I give you a point.
+1 For a good practical answer, if someone has a problem with it explain why (so we can show you Martin is right)
+1 from me to, std::vector<> is great. A minor nitpick would be to use size_t instead of int for the ctor.
@Andreas Magnusson: Wee spotted. Updated. But if your vector size is overflowing a signed int I think you have other problems.
16

No this is not possible. Array declarations in headers must have constant sized value. Otherwise it's impossible for constructs like "sizeof" to function properly. You'll need to declare the array as a pointer type and use new[] in the constructor. Example.

class Test { 
    int *a;
public:
    Test(int size) {
       a = new int[size];
    }
    ~Test() { delete [] a; }
private:
    Test(const Test& other);
    Test& operator=(const Test& other);
};

5 Comments

Need to add CopyConstructor and assignment operator and call the correct version od delete. Or use a vector.
Drat. I usually call other people out for the same problem ... Will fix shortly
Double Wrong ;( It's logical friday
Definately agree vector is better. The original sample did not use STL so I decided to answer without STL. STL makes C++ so much better. I'm finding it harder and harder to separate the two
You most probably also need a variable which stores the size of a.
5

As other answers have pointed out, the size of an array is fixed at compile time. However, by using templates you can parameterise the size at compile time:

template <int N> class Test {
    int a[N];
public:
    Test() { }
};

Test<5> test;
Test<40> biggertest;

This technique does not let you compute the size at run time (as the dynamic std::vector solution does), but depending on your needs this may be sufficient.

4 Comments

That works, but each version of Test is now a different class. Thus no implicit friendship (thus no accesses for copying etc).
Not that you could copy a Test<2> to a Test<1> anyway -- it wouldn't fit. Also, no polymorphism - Test<1> and Test<2> are incompatible types, so every function that handles them has to be templated too.
no worries. he can still template the operator= and the cctor.
@Greg: Interesting tip. Yet another reason why Generics != Templates. Or is it Generics < Templates? ;-)
3

First of all, it is generally better to initialize things in the initialization list of the constructor, not in the body of the constructor.

You can only initialize an array with a predefined bound if you know that bound at compile time. In this situation, you will need to dynamically allocate the space.

You must remember then to have a destructor that would delete the array when the object is destroyed or you would get a memory leak.

Comments

2

See Martin's solution (use std::vector), and remember that even if you need to pass a buffer to a C API std::vector lets you do it by passing &vec[0] :

std::vector<char> vec(10);
memset(&vec[0], 0, vec.size());

It's guaranteed to work, but only if the vector isn't empty (C++ quirks, <sigh>).

1 Comment

I use the &vec[0] trick a lot, though the memset() is in this case unnecessary as vec would already have been initialized to all zeroes.
0

No, this is not possible. You should use a dynamic array such as an std::vector. C99 allows a struct to have an unsized array as the last member only, but even when you do this you still have to manually allocate the memory yourself, e.g. with malloc().

Comments

0

What you're talking about is not possible. Classes always have a constant size. You could have your class use a pointer to a dynamically allocated array or you could use a std::vector.

Comments

Your Answer

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