zaratustra
zaratustra

Reputation: 8738

Determine array size in constructor initializer

In the code below I would like array to be defined as an array of size x when the Class constructor is called. How can I do that?

class Class
{
public:
  int array[];
  Class(int x) : ??? { }
}

Upvotes: 27

Views: 94467

Answers (11)

Miguel Leon
Miguel Leon

Reputation: 200

Don't you understand there is not need to use vector, if one wants to use arrays it's a matter of efficiency, e.g. less space, no copy time (in such case if handled properly there is not even need to delete the array within a destructor), etc. wichever reasons one has.

the correct answer is: (quoted)

class Class
{
   int* array;
   Class(int x) : array(new int[x]) {};
};

Do not try to force one to use non optimal alternatives or you'll be confusing unexperienced programmers

Upvotes: 5

Spacefish
Spacefish

Reputation: 323

Like already suggested, vector is a good choice for most cases.

Alternatively, if dynamic memory allocation is to be avoided and the maximum size is known at compile time, a custom allocator can be used together with std::vector or a library like the embedded template library can be used.

See here: https://www.etlcpp.com/home.html

Example class:


#include <etl/vector.h>

class TestDummyClass {
public:
    TestDummyClass(size_t vectorSize) {
        if(vectorSize < MAX_SIZE) {
            testVector.resize(vectorSize);
        }
    }

private:
    static constexpr uint8_t MAX_SIZE = 20;
    etl::vector<int, MAX_SIZE> testVector;
    uint8_t dummyMember = 0;
};

Upvotes: 1

Sherazi Rajput
Sherazi Rajput

Reputation: 41

I had the same problem and I solved it this way

class example
{
  int *array;

  example (int size)
  {
    array = new int[size];
  }
}

Upvotes: 4

Jeff Diamond
Jeff Diamond

Reputation: 779

You folks have so overcomplicated this. Of course you can do this in C++. It is fine for him to use a normal array for efficiency. A vector only makes sense if he doesn't know the final size of the array ahead of time, i.e., it needs to grow over time.

If you can know the array size one level higher in the chain, a templated class is the easiest, because there's no dynamic allocation and no chance of memory leaks:

template < int ARRAY_LEN > // you can even set to a default value here of C++'11

class MyClass
  {   
  int array[ARRAY_LEN]; // Don't need to alloc or dealloc in structure!  Works like you imagine!   
  }

// Then you set the length of each object where you declare the object, e.g.

MyClass<1024> instance; // But only works for constant values, i.e. known to compiler

If you can't know the length at the place you declare the object, or if you want to reuse the same object with different lengths, or you must accept an unknown length, then you need to allocate it in your constructor and free it in your destructor... (and in theory always check to make sure it worked...)

class MyClass
  {
  int *array;

  MyClass(int len) { array = calloc(sizeof(int), len); assert(array); }   
  ~MyClass() { free(array); array = NULL; } // DON'T FORGET TO FREE UP SPACE!
  }

Upvotes: 76

Cătălin Pitiș
Cătălin Pitiș

Reputation: 14341

You can't initialize the size of an array with a non-const dimension that can't be calculated at compile time (at least not in current C++ standard, AFAIK).

I recommend using std::vector<int> instead of array. It provides array like syntax for most of the operations.

Upvotes: 29

user563910
user563910

Reputation: 161

Sorry for necroing this old thread. There is actually a way to find out the size of the array compile-time. It goes something like this:

#include <cstdlib>

template<typename T>
    class Class
    {
        T* _Buffer;

        public:
        template<size_t SIZE>
            Class(T (&static_array)[SIZE])
            {
                _Buffer = (T*)malloc(sizeof(T) * SIZE);

                memcpy(_Buffer, static_array, sizeof(T) * SIZE);
            }

            ~Class()
            {
                if(_Buffer)
                {
                    free(_Buffer);
                    _Buffer = NULL;
                }
            }
    };

int main()
{
    int int_array[32];
    Class<int> c = Class<int>(int_array);

    return 0;
}

Alternatively, if you hate to malloc / new, then you can create a size templated class instead. Though, I wouldn't really recommend it and the syntax is quite ugly.

#include <cstdio>

template<typename T, size_t SIZE>
    class Class
    {
        private:
            T _Array[sz];
        public:
            Class(T (&static_array)[SIZE])
            {
                memcpy(_Array, static_array, sizeof(T) * SIZE);
            }
    };

int main()
{
    char int_array[32];
    Class<char, sizeof(int_array)> c = Class<char, sizeof(int_array)>(int_array);
    return 0;
}

Anyways, I hope this was helpful :)

Upvotes: 3

AFoglia
AFoglia

Reputation: 8128

I don't think it can be done. At least not the way you want. You can't create a statically sized array (array[]) when the size comes from dynamic information (x).

You'll need to either store a pointer-to-int, and the size, and overload the copy constructor, assignment operator, and destructor to handle it, or use std::vector.

class Class
{
  ::std::vector<int> array;
  Class(int x) : array(x) { }
};

Upvotes: 5

JaredPar
JaredPar

Reputation: 754665

Instead of using a raw array, why not use a vector instead.

class SomeType {
  vector<int> v;
  SomeType(size_t x): v(x) {}
};

Using a vector will give you automatic leak protection in the face of an exception and many other benefits over a raw array.

Upvotes: 1

Shree
Shree

Reputation: 4747

Declare your array as a pointer. You can initialize it in the initializer list later through through new.

Better to use vector for unknown size.

You might want to look at this question as well on variable length arrays.

Upvotes: 0

anon
anon

Reputation:

You can't do it in C++ - use a std::vector instead:

#include <vector>

struct A {
   std::vector <int> vec; 
   A( int size ) : vec( size ) {
   }
};

Upvotes: 0

John Dibling
John Dibling

Reputation: 101456

Use the new operator:

class Class
{
   int* array;
   Class(int x) : array(new int[x]) {};
};

Upvotes: 16

Related Questions