I have this method:
void createSomething(Items &items)
{
int arr[items.count]; // number of items
}
But it's throwing an error:
expression must have a constant value
I found just this solution:
int** arr= new int*[items.count];
so I'm asking is there a better way how do handle this?
You can use a std::vector
void createSomething(Items &items)
{
std::vector<int> arr(items.count); // number of items
}
The reason your first method won't work is that the size of an array must be know at compile time (without using compiler extensions), so you have to use dynamically sized arrays. You can use new to allocate the array yourself
void createSomething(Items &items)
{
int* arr = new int[items.count]; // number of items
// also remember to clean up your memory
delete[] arr;
}
But it is safer and IMHO more helpful to use a std::vector.
Built in arrays & std::array always require a constant integer to determine their size. Of course in case of dynamic arrays (the one created with new keyword) can use a non-constant integer as you have shown.
However std::vector (which of course internally a dynamic array only) uses a is the best solution when it comes to array-type applications. It's not only because it can be given a non-constant integer as size but also it can grown as well as dynamically quite effectively. Plus std::vector has many fancy functions to help you in your job.
In your question you have to simply replace int arr[items.count]; with :-
std::vector<int> arr(items.count); // You need to mention the type
// because std::vector is a class template, hence here 'int' is mentioned
Once you start with std::vector, you would find yourself preferring it in 99% cases over normal arrays because of it's flexibility with arrays. First of all you needn't bother about deleting it. The vector will take care of it. Moreover functions like push_back, insert, emplace_back, emplace, erase, etc help you make effective insertions & deletions to it which means you don't have to write these functions manually.
For more reference refer to this
Related
For my project I need to store pointers to objects of type ComplicatedClass in an array. This array is stored in a class Storage along with other information I have omitted here.
Here's what I would like to do (which obviously doesn't work, but hopefully explains what I'm trying to achieve):
class ComplicatedClass
{
...
}
class Storage
{
public:
Storage(const size_t& numberOfObjects, const std::array<ComplicatedClass *, numberOfObjects>& objectArray)
: size(numberOfObjects),
objectArray(objectArray)
{}
...
public:
size_t size;
std::array<ComplicatedClass *, size> objectArray;
...
}
int main()
{
ComplicatedClass * object1 = new ComplicatedClass(...);
ComplicatedClass * object2 = new ComplicatedClass(...);
Storage myStorage(2, {object1, object2});
...
return 0;
}
What I am considering is:
Using std::vector instead of std::array. I would like to avoid this because there are parts of my program that are not allowed to allocate memory on the free-store. As far as I know, std::vector would have to do that. As a plus I would be able to ditch size.
Changing Storage to a class template. I would like to avoid this because then I have templates all over my code. This is not terrible but it would make classes that use Storage much less readable, because they would also have to have templated functions.
Are there any other options that I am missing?
How can I pass and store an array of variable size containing pointers to objects?
By creating the objects dynamically. Most convenient solution is to use std::vector.
size_t size;
std::array<ComplicatedClass *, size> objectArray;
This cannot work. Template arguments must be compile time constant. Non-static member variables are not compile time constant.
I would like to avoid this because there are parts of my program that are not allowed to allocate memory on the free-store. As far as I know, std::vector would have to do that.
std::vector would not necessarily require the use of free-store. Like all standard containers (besides std::array), std::vector accepts an allocator. If you implement a custom allocator that doesn't use free-store, then your requirement can be satisfied.
Alternatively, even if you do use the default allocator, you could write your program in such way that elements are inserted into the vector only in parts of your program that are allowed to allocate from the free-store.
I thought C++ had "free-store" instead of heap, does it not?
Those are just different words for the same thing. "Free store" is the term used in C++. It's often informally called "heap memory" since "heap" is a data structure that is sometimes used to implement it.
Beginning with C++11 std::vector has the data() method to access the underlying array the vector is using for storage.
And in most cases a std::vector can be used similar to an array allowing you to take advantage of the size adjusting container qualities of std::vector when you need them or using it as an array when you need that. See https://stackoverflow.com/a/261607/1466970
Finally, you are aware that you can use vectors in place of arrays,
right? Even when a function expects c-style arrays you can use
vectors:
vector<char> v(50); // Ensure there's enough space
strcpy(&v[0], "prefer vectors to c arrays");
I have this method:
void createSomething(Items &items)
{
int arr[items.count]; // number of items
}
But it's throwing an error:
expression must have a constant value
I found just this solution:
int** arr= new int*[items.count];
so I'm asking is there a better way how do handle this?
You can use a std::vector
void createSomething(Items &items)
{
std::vector<int> arr(items.count); // number of items
}
The reason your first method won't work is that the size of an array must be know at compile time (without using compiler extensions), so you have to use dynamically sized arrays. You can use new to allocate the array yourself
void createSomething(Items &items)
{
int* arr = new int[items.count]; // number of items
// also remember to clean up your memory
delete[] arr;
}
But it is safer and IMHO more helpful to use a std::vector.
Built in arrays & std::array always require a constant integer to determine their size. Of course in case of dynamic arrays (the one created with new keyword) can use a non-constant integer as you have shown.
However std::vector (which of course internally a dynamic array only) uses a is the best solution when it comes to array-type applications. It's not only because it can be given a non-constant integer as size but also it can grown as well as dynamically quite effectively. Plus std::vector has many fancy functions to help you in your job.
In your question you have to simply replace int arr[items.count]; with :-
std::vector<int> arr(items.count); // You need to mention the type
// because std::vector is a class template, hence here 'int' is mentioned
Once you start with std::vector, you would find yourself preferring it in 99% cases over normal arrays because of it's flexibility with arrays. First of all you needn't bother about deleting it. The vector will take care of it. Moreover functions like push_back, insert, emplace_back, emplace, erase, etc help you make effective insertions & deletions to it which means you don't have to write these functions manually.
For more reference refer to this
Depending on a variable, I need to select the SeedPositions32 or SeedPositions16 array for further use. I thought a pointer would allow this but I can't seed to make it work. How do you declare a pointer to a C++11 std::array? I tried the below.
array<int>* ArrayPointer;
//array<typedef T, size_t Size>* ArrayPointer;
array<int,32> SeedPositions32 = {0,127,95,32,64,96,31,63,16,112,79,48,15,111,80,
47,41,72,8,119,23,104,55,87,71,39,24,7,56,88,103,120};
array<int,16> SeedPositions16 = {...}
std::array has a template parameter for size. Two std::array template instantiations with different sizes are different types. So you cannot have a pointer that can point to arrays of different sizes (barring void* trickery, which opens its own can of worms.)
You could use templates for the client code, or use std::vector<int> instead.
For example:
template <std::size_t N>
void do_stuff_with_array(std::array<int, N> the_array)
{
// do stuff with the_array.
}
do_stuff_with_array(SeedPositions32);
do_stuff_with_array(SeedPositions16);
Note that you can also get a pointer to the data:
int* ArrayPtr = SeedPositions32.data();
but here, you have lose the size information. You will have to keep track of it independently.
You can simply access the content of the std::array as a raw C-like array pointer using the std::array::data() member function:
int* arrayPointer = useSeedPositions32 ? SeedPositions32.data() : SeedPositions16.data();
In his answer juanchopanza explained very well why what you want cannot work.
The question is why would you want to do that? There is no way where you could use a (pointer to) std::array<int,32> in place of std::array<int,16>.
The point of std::array<> is to keep track of the number of elements at compile time (and also to avoid memory allocation for small fixed-sized arrays). If you instead want the number of elements to be managed at run time, you should presumably not use std::array<>, but std::vector.
The alternative of obtaining a pointer to the underlying data (using std::array::data() as proposed in other answers) and keeping track of the number of elements by yourself is somewhat dangerous and not really recommendable. The problem is that you must ensure that the pointer is never dangling.
Finally, I cannot find any possible use case. In order to use your pointer, you must declare both an array<int,32> and an array<int,16> object, yet use only one of them.
Why don't you simply only declare a array<int,32> and use only its first 16 elements if not all 32 are needed?
You could do something like this:
int * myArray = use32 ? &SeedPositions32[0] : &SeedPositions16[0];
So std::array and boost::array (which are almost identical, and I will hereafter refer to ambiguously as just "array") were designed to provide a container object for arrays that does not incur the overheads of vector that are unnecessary if the array does not dynamically change size. However, they are both designed by taking the array size not as a constructor parameter but a template argument. The result: vector allows dynamic resizing after object creation; array requires the size to be known at compile time.
As far as I can see, if you have an array for which you will knows the size at object creation but not at compile time, then your only options are 1) unnecessarily incur extra overheads by using vector, 2) use the (non-container type) native array (e.g., int foo[42];), or 3) write your own array-wrapper class from scratch. So is this correct, that this is an in-between case where you may want to use array rather than vector, but cannot? Or is there some magic I can do that will may array work for me?
Here's a little detail (ok, a lot) on what inspired this question, in case it helps you understand:
I have a module - say the caller - that will repeatedly produce binary data at runtime (unsigned char[], or array), and then pass it to another module - say the callee. The callee module does not modify the array (it will make a copy and modify that if necessary), so once the caller module creates the array initially, it will not change size (nor indeed contents). However, two problems arise: 1) The caller may not generate arrays of the same size each time an array is generated - it will know the array size at rutime when it creates the array, but not at compile time. 2) The method for caller to pass the array to callee needs to be able to take an array of whatever size the caller passes to it.
I thought about making it a templated function, e.g.,
template<size_t N> void foo(const array<unsigned char, N>& my_array);
However, I'm using an interface class to separate interface from implementation in the callee module. Therefore, the function must be a virtual method, which is mutually exclusive with being templated. Furthermore, even if that were not an issue, it would still have the same problem as #1 above - if the array sizes are not known at compile time then it also cannot resolved the templated function at compile time.
My actual funciton:
virtual void foo(const array<unsigned char, N>& my_array); // but what is N???
So in summary, am I correct that my only real choices are to use a vector or native array, e.g.,
virtual void foo(const vector<unsigned char> my_array); // unnecessary overhead
virtual void foo(const unsigned char[] my_array, size_t my_array_len); // yuk
Or is there some trick I'm overlooking that will let me use a std::array or boost::array?
Until we have std::dynarray in C++11, you can use std::unique_ptr:
std::unique_ptr<Foo[]> arr(new Foo[100]);
You can use this as arr[0], arr[1], etc., and it will call the correct delete[] upon destruction. The overhead is minimal (just the pointer).
I think the only difference between an array-typed unique pointer and std::dynarray is that the latter has iterators and and size other "containery" properties, and that it'll be in the "Containers" section rather than the "general utilities". [Update: And that compilers may choose to natively support dynarray and optimize it to use stack storage.]
You simply cannot use any form of std::array if you don't know the length at compile time.
If you don't know the size of your array at compile time, seriously consider using std::vector. Using variable length arrays (like int foo[n]), is not standard C++ and will cause stack overflows if given length is big enough. Also you cannot write any array-like-wrapper with (measurably) less overhead than std::vector.
I would just use
virtual void foo(const unsigned char* my_array, size_t my_array_len);
And call it like
obj.foo(&vec[0], vec.size());
There is no overhead attached and it does what you want. In addition to normal arrays (int foo[42]) this can also be called with vectors and std::arrays with zero overhead.
Other considerations:
Arrays are allocated on the stack. This is much faster than allocating on the heap.
Arrays always initialize all their elements when they are created.
So:
class Foo;
std::array<Foo, 100> aFoo;
constructs 100 Foo objects, (calls Foo::Foo() 100 times) while
std::vector<Foo> vFoo;
vFoo.reserve(100);
reserves space for 100 Foo objects (on the heap), but doesn't construct any of them.
Coming from a PHP background, I'm trying to learn C++, since I find it an interesting language. As a practice I want to create a simple Vector class using templates, which is not to hard. However, I run into one problem.
I have created the following template class:
template <typename T>
class Vector
{
public:
Vector(int length);
~Vector(void);
int getLength();
T& operator[] (const int index);
private:
T *_items;
int _count;
};
template <typename T>
Vector<T>::Vector(int length)
{
_items = new T[length];
_count = length;
}
template <typename T>
T& Vector<T>::operator[]( const int index )
{
if (index >= getLength() || index < 0)
throw exception("Array out of bounds.");
return _items[index];
}
All functions are implemented, but they're not relevant to my question, so I haven't copied them here.
This class works as expected, with one exception:
If I want to create a vector of array's, it doesn't work.
e.g.:
Vector<int[2]> someVector(5);
What I obviously want is that the _items property of the vector class will be an int[5][2]. However, since the compiler replaces the 'T' with 'int[2]', the _items property will be int[2][5] (or at least, that's what I understood from debugging, please correct me if I'm wrong). As a result, the [] operator doesn't work correctly anymore, and therefore this whole class is useless for arrays.
Is there a way to solve this problem, so that this class also works for arrays? And if that's not possible, is there a way to prevent this class being initialized with arrays?
Edit: Thanks for all your responses so far. However, I might have been not entirely clear with my question. First of all, I created this class to get used to c++, I know there is a std::vector class, and I also now that it's better to use a vector of vectors. That's not really the problem. I just want to understand templates better, and c++ in general, so I want to know how to deal with this type of problems. I want to be able to create classes which don't make the program crash. If I, or someone else, would use this class right now and tried to use primitive arrays instead of vectors for this class, at some point the program will crash since the array is wrong (Vector(y) becomes int[x][y] instead of int[y][x] internally). So I want a solution which either creates the correct array, or prevents the vector being initialized with arrays at all.
Quite simply, don't ever use the in-built primitive arrays. For anything. They suck, tremendously. Always use a class wrapper such as boost::array, if you don't have TR1 or C++0x both of which also provide an array class. A Vector<boost::array<int, 2>> will trivially compile.
Why not use primitive arrays?
They have hideous implicit conversions to pointers, forget their size at the drop of a hat, aren't first-class citizens (can't assign to them, for example), don't check their bounds, for example. boost::array<int, 2> is exactly a primitive array without crappy conversions, is fully generic- for example, your Vector template works fine with a boost::array<int, 2> off the bat, and it can do bounds checking in the at() function.
I'm not suggesting using a dynamic array instead. boost::array is not a dynamically sized array. It is a constant size, value type array, that will not convert to a pointer, it has functions for use in the Standard library like begin, end, size, and it can be treated like any other type- unlike arrays, which have a dozen special rules- as you've found out.
I see a few things wrong with this.
If you are making a generic vector class, why deal with a vector of arrays rather than a vector of vectors?
Rather than defining a vector of type int[2], try making a vector of vectors of size 2 with something like this:
Vector<Vector<int>> vector(5);
for (int i = 0; i < 5; i++)
{
vector[i] = Vector<int>(2);
}
Rather than using a constant sized array, try using a pointer.
Rather than using a pointer to arrays of size 2, use a pointer to a pointer, and allocate two spaces for that pointer. Pointers are a lot easier to deal with in C++ because you can simply pass the address of the pointer rather than having to copy the entire array. It's generally very bad form to pass arrays.
Add a default parameter to your constructor
Rather than declaring the constructor with Vector(int length);, try using Vector(int length = 0); so that if the user doesn't specify a length it will default to a size of zero.
Finally, are you aware that there is in fact an std::vector, or are you aware of this and simply trying to replicate it? Templates are known to be one of the hardest subjects of C++, good luck!
The condition must say index >= getLength(), because getLength() is not an allowed index value too (the first element's index is 0, the last's is getLength()-1)