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)
Related
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.
I would like to know, if I have a class with an array attribute whose size is not the same for all instances :
class myObject{
private:
int size;
int* array;
// other methods/attributes
};
Is it obligatory allocated using new ?
explicit myObject(int size = 0):size(size){
array = new int[size];
}
Even if in the main(), I always use constant parameters to create the instances of the class ? (Meaning I know every array size at compile time).
int main{
myObject object (5);
return 0;
}
Apparently something like :
private:
int size;
int array[size];
wont work, no ?
That means that array attribute whose size are not constant of the class are obligatory on the heap ?
Thank you for your answers,
That class contains no array. What you called array is a pointer; you cannot store any ints in it. If you really do just store a pointer, you'll have to allocate the memory yourself somehow; it can't magically appear. You'll also have to deallocate it yourself, and make sure that copying and assigning myObject objects doesn't cause any issues.
However, it's unlikely that a pointer is really the best way to do things. The standard library provides the std::vector class template which lets you use almost exactly the syntax you want:
class myObject {
std::vector<int> vector;
public:
myObject() {};
explicit myObject(std::size_t n) : vector(n) {}
};
With this in place you can create myObjects and they'll have the right amount of storage ready for them. It'll likely be dynamically allocated using operator new[], just like if you'd do it manually, but you don't have to worry about copying or deleting it.
int main() {
myObject a; // default-constructed, vector is empty.
myObject b(10); // std::size_t constructor, vector has 10 elements.
} // scope exit, b and a destroyed.
You can use the vector member much like if it was an array; the only thing it does not support is implicit decay to pointer, but the data member function makes up for even that.
As an alternative, if you always know the size at compile-time you can change the class into a class template and make the size a template parameter:
template<std::size_t N>
class myObject{
std::array<int, N> array;
// other methods/attributes
};
However, note that you now cannot use myObject<10> to a function expecting myObject<20>.
It is unlikely that you want more control than the above possibilities provide -- std::vector can be given an allocator, so it can do almost all work for you -- you could use std::unique_ptr<int[]> and make_unique together to make things work for you. However, if you need this kind of power, you probably know it yourself.
As a closing note, if you're just learning C++ and your book doesn't cover std::vectors somewhere early on, perhaps it's best to get a different book; they're one of the most commonly-useful data structures in the standard library and definitely not something to be left in an appendix.
If you need a variable sized array as a member of a class, don't use built-in arrays directly. Instead, use std::vector<T>, e.g.:
class myObject {
std::vector<int> array;
public:
explicit myObject(int size = 0): array(size){}
};
You can get the std:vector<int>'s size using array.size(), i.e., there is no need to store the size separately. Also, the content is automatically default initialized.
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
Let's say I have a class that has a member which is an array. Is it possible to define its size upon construction/at run-time, in the following way:
class myClass {
private:
int myArray[n]
public:
myClass();
someOtherMethod();
};
Where n is a variable that is defined based on user input. If not, what would be the best alternative?
It depends.
Semantically, there are 3 types of arrays:
arrays with a size fixed at compile time
arrays with a size fixed at runtime
arrays with a dynamic size
C++ directly supports the first and third cases, respectively with regular arrays and the std::vector class.
C also supports the second type with two constructs:
variable length arrays (on the stack)
the oldie struct hack or tail-padding
I would advise, in C++, using the std::vector class in your case. It provides more than what you need, but is simpler to use.
On the other hand, you can still use tail-padding, even in C++. It does require careful engineering though.
Use a vector.
class myClass {
private:
std::vector<int> myArray;
public:
myClass();
someOtherMethod();
};
myClass::myClass (int size)
: myArray (size)
{
...
}
Then, you can fill in the vector as you would an array. Alternatively, as Nawaz points out, use reserve(), which reserves space for new elements, and/or push_back(), which adds elements onto the back, one at a time.
The class template std::vector is designed for this purpose.
class myClass {
private:
std::vector<int> myArray;
public:
myClass(int size);
someOtherMethod();
};
myClass::myClass(int size) : myArray(size)
{
}
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.