c++ array declaration in a header

38,871

Solution 1

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

Solution 2

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

Solution 3

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.

Solution 4

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.

Solution 5

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

Share:
38,871
Admin
Author by

Admin

Updated on July 05, 2022

Comments

  • Admin
    Admin almost 2 years

    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!

  • Martin York
    Martin York over 15 years
    Need to add CopyConstructor and assignment operator and call the correct version od delete. Or use a vector.
  • JaredPar
    JaredPar over 15 years
    I wish people would add comments when marking down answers. At least you're back to 0
  • JaredPar
    JaredPar over 15 years
    Drat. I usually call other people out for the same problem ... Will fix shortly
  • Martin York
    Martin York over 15 years
    That works, but each version of Test is now a different class. Thus no implicit friendship (thus no accesses for copying etc).
  • John Dibling
    John Dibling over 15 years
    Haters love to hate anonymously. Hate the haters! I give you a point.
  • orip
    orip over 15 years
    +1 For a good practical answer, if someone has a problem with it explain why (so we can show you Martin is right)
  • JaredPar
    JaredPar over 15 years
    Double Wrong ;( It's logical friday
  • Steve Jessop
    Steve Jessop over 15 years
    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.
  • JaredPar
    JaredPar over 15 years
    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
  • Johannes Schaub - litb
    Johannes Schaub - litb over 15 years
    no worries. he can still template the operator= and the cctor.
  • James Schek
    James Schek over 15 years
    @Greg: Interesting tip. Yet another reason why Generics != Templates. Or is it Generics < Templates? ;-)
  • Andreas Magnusson
    Andreas Magnusson over 15 years
    +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
    Andreas Magnusson over 15 years
    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.
  • Martin York
    Martin York over 15 years
    @Andreas Magnusson: Wee spotted. Updated. But if your vector size is overflowing a signed int I think you have other problems.
  • ypnos
    ypnos over 15 years
    You most probably also need a variable which stores the size of a.