1

How can I define an array as a member of class while its size determined somewhere else and actually it is passed to the constructor.

More detail: There is an array of integer numbers and is defined a public member in class.

class foo {
  public:
    int *arr[];
    int s;
};

However the size of array is passed in the constructor.

foo::foo()
        : s (array_size)
{
}

What is the correct syntax of doing such thing?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
mahmood
  • 23,197
  • 49
  • 147
  • 242

5 Answers5

3

The correct way of doing this is to use the STL and std::vector< int > for such tasks. The following is a rough outline that may work for you:

#include <vector>

...

class foo
{
    public:
        std::vector< int > arr_;

        ...

        foo(const int* numbers, int numberCount)
        : arr_(numbers, numbers+numberCount)
        {
        }

        ...

        int size() const
        {
            return arr_.size();
        }

        ...

        int& operator [] (int index)
        {
           return arr_.at(index);
        }
};

Further information on vectors can be found here. Further suggestions:

  • don't make your instance variables public if there is no compelling reason to do so.
  • name instance variables somehow special (for example by appending a _).
  • many people dislike classes that are named all lowercase.
hochl
  • 12,524
  • 10
  • 53
  • 87
  • I wanted to index the array in an easy way. like "arr[ i ] = 1;" – mahmood Feb 28 '12 at 14:08
  • 1
    @mahmood vector implements `operator[]` - you can use subscript element access, just like a raw array. as a bonus, `vector` adds additional error detection and convenience features. it manages the count, and the reallocations for you. no losses there ;) – justin Feb 28 '12 at 14:12
  • using `vector`, I have to push back at the end. Or I have to user `insert()`. However, the first argument is an iterator. So `v.insert( i, 1);` doesn't work – mahmood Feb 28 '12 at 14:15
  • @mahmood: If you don't want to use `push_back()` for some reason, you can set the size with `resize()` (or in the constructor), then assign elements like `arr[i] = 1;`. – Mike Seymour Feb 28 '12 at 14:18
  • 1
    @mahmood: Only if you need the vector to grow, which is a feature arrays don't have. You can `resize` to whatever you need and then use `operator[]` (i.e. `v[1] = 5`) in the same way that you would with an array. I suggest that you get an introductory book on C++ and follow from there. – David Rodríguez - dribeas Feb 28 '12 at 14:20
3

Your class appears to be attempting to define an array of 'pointers to int', not an array of int as you suggest. However, the classic answer is precisely that you use a 'pointer to int' and allocate the array in the constructor and release it in the destructor. To a first approximation:

class foo
{
public:
    int *arr;
    int  s;
    foo(int sz) : s(sz) { arr = new int [s]; }
   ~foo()               { delete [] arr; }
};

If you're going to go down this route, you will also need to provide an assignment operator and a copy constructor (as Mike Seymour reminds me - thanks, Mike); the default versions the compiler will write for you if you don't write them for yourself will be wrong - horribly wrong. (The SO question "What is the Rule of Three?" covers this.)

However, this is (probably) not exception safe, and you'd be well advised to use std::vector<int> instead of a plain pointer:

class foo
{
public:
    std::vector<int> arr;
    foo(int sz) : arr(sz) { }
};

You don't need to store the size explicitly; the vector does that for you.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • this means array of int and not array of pointers to int. Right? – mahmood Feb 28 '12 at 14:20
  • If you're going to suggest manual allocation, you really should mention the [Rule of Three](http://stackoverflow.com/questions/4172722). – Mike Seymour Feb 28 '12 at 14:21
  • Yes (this is an array of `int`). I assumed you wanted an array of `int` as you stated in the question, rather than what appears to be an array of pointers to `int` as other people seem to be assuming, based on the notation used in your class code. – Jonathan Leffler Feb 28 '12 at 14:22
  • In modern C++, yes - the accepted wisdom is that `std::vector` is normally the better solution to most problems with arrays (unless you must avoid dynamic memory allocation for some reason, but then you can't have arrays of varying sizes). Plain old arrays get short shrift these days. – Jonathan Leffler Feb 28 '12 at 15:03
1

Well first off, not sure why you're using an array of int pointers, but who am I to question your design.. Anywho, you can do this with a pointer and dynamic allocation. Declare your array as...

int **arr;

and initialize it in the ctor as..

*arr = new int*[s];

Remember to clean it up on the dtor with delete[]. Another alternative is to use std::vector<int*>

Brian Mains
  • 50,520
  • 35
  • 148
  • 257
MGZero
  • 5,812
  • 5
  • 29
  • 46
1

Maybe this is not exactly what you want, but I would do it with a template parameter

template<int T>
class Foo
{
    public:
    int array[T];
    int s;
};

You instantiate this class like

Foo<1024> * f = new Foo<1024> ();
svenfx
  • 501
  • 3
  • 5
  • 2
    Doesn't that need to be template? – BoBTFish Feb 28 '12 at 14:15
  • yes, that's a non-type template argument. unless the number is known at compilation type this won't work. – Karoly Horvath Feb 28 '12 at 14:18
  • Yes, and that runs fine. Sorry, I had not tested it before writing it down. Fixed. – svenfx Feb 28 '12 at 14:19
  • 1
    Ignoring the notational issue, you probably don't want a separate type for each separate array size. And you can't have a separate type if the size varies at runtime, as the question suggests. – Jonathan Leffler Feb 28 '12 at 14:19
  • @JonathanLeffler: Mahmood suggested a constructor param, so this solution is equivalent. And it's just an idea which works out for the simple case - however if you have a more complex idea, you might want to reconsider that issue :) – svenfx Feb 28 '12 at 14:24
0
class foo {
   public:
     std::vector m_vec;
     foo(uint32_t size) : m_vec(size) { }
};
perreal
  • 94,503
  • 21
  • 155
  • 181