Array inside an object - c++

It's possible to create an array like this - if size is defined before arr.
const int size = 5;
int arr[size];
But it's not possible, when size and arr are inside object or struct:
struct A{
A(int s) : size(s)
{}
const int size;
int arr[size]
};
A(5);
Why is it so? It's seems kinda illogical, because in both cases size of array is known in compilation time.

It's seems kinda illogical, because in both cases size of array is known in compilation time.
The compiler cannot distinguish between your example and this:
int i = std::rand(); // not a compile time constant
A a(i);
On the other hand, it needs to know the size of the array at compile time. Two instances of A cannot have different size. So the size of the array cannot depend on something that can be set at runtime.
On the other hand, C++11 provides constexpr, which allows you to propagate compile-time constants through expressions and lets you use these to initialize arrays.

in both cases size of array is known in compilation time.
Nope, a const class member can be set at run-time.
In fact, even a non-member doesn't always work:
int x;
cin >> x;
const int y = x;
int z[y]; //ILLEGAL
Just use a std::vector.

When the compiler compiles A, there is in fact no guarantee that it is a compile-time argument. It just happens to be one. I could equally do
int main() {
std::cin >> i;
A(i);
}
If you want to pass it a constexpr argument, you will need to use a template. Else, you will need to use a run-time container like std::vector.

You should use std::vector<int> instead of raw arrays if you want a dynamically resizeable array.
You cannot do what you're trying to do inside the class or struct because your size member has no defined value.

Because in C++ when you initialize a C-style array with a size argument, the size must be a compile-time integral constant.
Otherwise the compiler doesn't know how big to make the variable when compiling.
If you don't like this, you should be using vector anyway.

In second case, if you take into consideration just class definition array size is not known in compilation time.
if making such classes was allowed you could write
A(5);
A(6);
that would be objects of different size, that would break alot, for example it would not be possible to keep such objects in the same array. It would be logical to say that those objects have different type, and that would be possible if you make your class template and pass size as template parameter.
if you want to use arrays of different size use std::vector or templates.

You need to dynamicly allocate the memory from your heap if it is not known before compile time.
int* arr = new int [size];
If you do not need the memory anymore you should delete the array.
delete[] arr;
And also as Tony said, it is better to use standart libary vectors

Related

[C++]Assinging an array a size during constructor

I'm honestly stuck on how to asssign an array's size during the call of the constructor. Also, I would like the array to be a 'const'. Is this possible during the constructor? Or do I have to do some more tricky stuff? Here is part of the code:
class CustomBitmap
{
public:
CustomBitmap(int width,int height);
~CustomBitmap(void);
private:
const int m_width;
const int m_height;
char const m_components[];
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "CustomBitmap.h"
CustomBitmap::CustomBitmap(int width,int height) : m_width(width), m_height(height)
// How do I implement the array? none of the syntax works, I tried m_components([width * height *4]) and all sorts of things along that line.
{}
CustomBitmap::~CustomBitmap(void) {}
An array has a fixed size (at least in standard C++), so you cannot assign a size to it at runtime, but have to specify its size at compile time.
If you want a variable size, use a std::vector, in your case
std::vector<char> m_components;
If the vector is const, then you won't be able to change/append to it, so I don't really see the point of making it const, unless you trivially initialize it in class (C++11) as e.g.
const std::vector<char> m_components(10, 'a'); // const char vector of 10 a's
or
const std::vector<char> m_components = {'a','b','c'}; // again C++11 in class initialization
You may also do something like
template<int N>
class CustomBitmap
{
...
char m_compontents[N];
}
but again, this is a template class for which you have to specify the template parameter N at compile time, i.e. instantiate it as e.g.
CustomBitmap<5> my_custom_bitmap; // now m_components has size 5
This kind of syntax:
m_components([width * height *4])
would be called variable length arrays. VLA. this is C99 norm.
You can't do it here because it exists within your type, which would make the type size itself variable, which is impossible because it is not template.
You can make it template with an integral parameter (rather than typename you use int) and then you can do what you want.
Howver, you should not do it, because your type will become enormous, which is a bad idea since automatically allocated types can be on the stack, which will explode the limit very quickly and cause a number of inefficiencies since compilers are not used to stack bloat.
You need to allocate on the heap, using std::vector is the best answer here. Also be aware for later that std::array<T,N> type exists to do what I described in the first paragraph.

Initializing std::array inside a function

I want to create a function that resizes a stack. It will create a new array with a larger or smaller size depending on the value of max, then copy the elements into that new array.
void resize(const int& max) {
std::array<Item, max> temp;
for (int i = 0; i < n; i++) {
temp.at(i) = a.at(i);
}
a = temp;
}
I know this will not run because max is not a constant expression. I absolutely don't know how to pass a constant int value. I tried:
void resize(constexpr int& max) //compiler says cannot make int arg constexpr
I don't want to do constexpr void resize because I don't need the function to be evaluated at compile time, and it didn't work anyway.
Note: I know this might be easier if I used std::vector because it's resizable, but I want to try to experiment with std::array.
What should I do?
I think you are mistaking compile-time constant and run-time constant. You cannot use std::array in this way. You want a container whose size is not compile-time constant, and that would be std::vector.
If you want your container's size to be constant throughout the runtime, you can either rely on self discipline (i.e : do not use push_back() or resize() etc..) Or you could write a wrapper class (.i.e a class that has-a std::vector as a member) and choose the methods of this class carefully to never resize the vector.
You can also use dynarray but it has been rejected from c++11 (and c++14 If I recall correctly)
PS: it is quite weird to name your method resize() and then say that you want constant-sized arrays =)
You do realize that if you call this method you are indeed changing the size of your array at runtime, in which case why not use std::vector and be done with it ?

static array allocation issue!

I want to statically allocate the array. Look at the following code, this code is not correct but it will give you an idea what I want to do
class array
{
const int arraysize;
int array[arraysize];//i want to statically allocate the array as we can do it by non type parameters of templates
public:
array();
};
array::array():arraysize(10)
{
for(int i=0;i<10;i++)
array[i]=i;
}
main()
{
array object;
}
If your array size is always the same, make it a static member. Static members that are integral types can be initialized directly in the class definition, like so:
class array
{
static const int arraysize = 10;
int array[arraysize];
public:
array();
};
This should work the way you want. If arraysize is not always the same for every object of type array, then you cannot do this, and you will need to use template parameters, dynamically allocate the array, or use an STL container class (e.g. std::vector) instead.
It has to be done using template parameters, otherwise sizeof(array) would be different for every object.
This is how you would do it using template parameters.
template <int N>
class array
{
int data[N];
// ...
};
Or, you could use an std::vector if you don't mind dynamic allocation.
C++ doesn't allow variable-length arrays (i.e. ones whose sizes are not compile-time constants). Allowing one within a struct would make it impossible to calculate sizeof(array), as the size could differ from one instance to another.
Consider using std::vector instead, if the size is known only at runtime. This also avoids storing the array size in a separate variable. Notice that allocating from heap (e.g. by std::vector) also allows bigger arrays, as the available stack space is very limited.
If you want it a compile-time constant, take a template parameter. Then you should be looking for Boost.Array, which already implements it.
The array size must be a compile time constant. You are almost there, you just need to initialize the const and make it a static as well. Or, use a dynamic array or a vector.
EDIT: note about this answer: This is most likely the wrong way to do this for your situation. But if you really need it to be an array (not a vector or whatever) and you really need it to be dynamically allocated, do the following:
class array
{
int *p_array;
public:
array(int size);
};
array::array(int size)
{
p_array = malloc(size * sizeof(int));
}
Just make sure you clean up (IE free p_array in your descructor)

Using templates to make items of varying length stay on stack?

The situation is that I have an array of items, and the items have an array inside. However, I want to make the array inside of variable length at declaration time, yet resizable at compile time.
So I would want something like:
class2<16>[] = new class2<16>[2048*1024];
Or whatever. Hopefully you get the idea.
Obviously making it have fixed array inside is easy, but the problem is the array can be HUGE so I don't want to have 2048*1024 calls to new, so I definitely don't want class2 to call any new or delete methods.
Is this even possible?
You can create a template parameter for your internal array-size. For example:-
template<int siz>
class Item{
int arr[siz];
};
int main() {
Item<15> items[10];
return 0;
}
std::tr1::array (addition to standard library in C++0x) and boost::array already exist, taking two template parameters: the type and count of items:
std::tr1::array<int, 16> something;
You can have any number of those arrays at run-time with the std::vector container:
std::vector<std::tr1::array<int, 16> > lots_of_arrays(2048*1024);
Only one dynamic allocation involved here.

c++ array declaration in a header

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