Determine array size in constructor initializer
Solution 1
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.
Solution 2
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!
}
Solution 3
Use the new operator:
class Class
{
int* array;
Class(int x) : array(new int[x]) {};
};
Solution 4
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) { }
};
Solution 5
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 :)
Related videos on Youtube
zaratustra
Updated on February 09, 2021Comments
-
zaratustra about 3 years
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) : ??? { } }
-
Brian about 15 yearsIf you plan to use C++ regularly, I strongly recommend you familiarize yourself with the standard template library. It makes working with collections of data much easier.
-
Brian about 15 yearsAs an aside, vectors make it relatively easy to work with the array without knowing the size in advance. It isn't necessary to know the size in advance; you can append elements to the end of a vector in (amortized) O(1) time anyhow using push_back.
-
zaratustra about 15 yearsUsing vectors brings new problems, since the class I'm trying to vectorize has protected "new" operators. But that wasn't what I asked so nevermind.
-
Mooing Duck almost 12 years@zaratustra: Why would that make a vector not work? It might need a custom allocator, but I doubt even that.
-
-
zaratustra about 15 yearsWhat would the syntax for using a vector in that situation be like?
-
Brian about 15 yearsDon't forget to call delete[] in the constructor if you use this code.
-
Admin about 15 yearsIf you do this you will also need a copy constructor , an assignment operator and a destructor. Useing a std::vector gives you exactly the same functionality but requires none of these.
-
DevSolar about 15 yearsvector< int > array; Class( x ) : array( x ) {};
-
Admin about 15 yearsbetter to use the vector for known size too
-
user2584401 about 15 yearsDo you mean "Using a vector will give you automatic leak protection"? :)
-
JaredPar about 15 years@mkb, that's twice today I've made fundamentally stupid comments. Must drink more coffee to wake up before i start posting ;)
-
Martin York about 15 yearsBAD idea. Doing the memory management on a pointer that acts like an array is not trivial in the presence of exceptions. Use std::vector or std::tr1::array.
-
Shree about 15 yearsaccepted, but this was just an option in response to the original question
-
Ricky65 about 10 yearsIn C++11 a superior method of determining the size of a built-in array is using a constexpr template function. For example: template < class T, std::size_t N > constexpr std::size_t size( const T (&array)[N] ) { return N; }
-
AMDG over 9 years+1 This actually answers the OP's question by initializing the size of an array, though it actually is replacing
int *array
which isn't an array, with the list in the constructor. @(anon) besides a copy constructor, an assignment operator, and a destructor, this truly answers the question. -
Tustin2121 over 5 yearsThis is a bad use of templates. I followed your suggestion and added an Array length template to my class, but now my Linker is yelling at me. Templated classes need to be either entirely inlined in the header, or I have to make new template versions of each method signature in the class for every array length I ever use. I want to -1 this answer now, but apparently my vote is locked in now...
-
Spacefish almost 4 yearsThis is a possible way but it makes it hard to use together with dynamic cast and prevents using a source file unless every case is instantiated explicitely. If a vector is desired without the use dynamic memory allocation, a custom allocator or using a library like the embedded template library might help.
-
Jacob Brunson about 2 yearsThank you; I have been searching everywhere for an answer like this. In certain situations this is exactly what is needed