2D arrays and dynamic arrays - c++

I have a class which just contains a 1D array of set size (17): However this array needs to be for every monitor that a user has and I am unsure whether to simply set say and array of size 10 limiting the user, or whether to try a more dynamic approach.
Excerpt from ScreenArray.h:
private:
unsigned long pixelArray[17];
I would like advise to which method(s) will work best for my problem and how would I go about constructing / allocating and accessing it?
EDIT: The array (Or the 2D part of the array) preferably dynamic to the size of the monitors currently connected. This contains the 1D array of set size 17.

As UnholySheep stated out, vector is a great tool to use in this situation:
Variable size;
Out of range protection;
Automatic memory management;
...
The only drawback I see may be a loss in performance, but because your vector is so small, you won't even be able to measure it, so this doesn't count.
You can use it like so:
// You'll need this one
#include <vector>
// Create you vector
// Replace TYPE with the type of it's members.
std::vector< TYPE > pixelArray;
// Add members to it
pixelArray.push_back( MEMBER );
// Access it as usual
pixelArray[n];

Related

Is it possible to have a std::vector of struct with a fexible array member?

I have a struct with a flexible array member that I need to use.
struct Record
{
uint32_t length;
Data contents[];
};
I'm able to initialize this and use it by doing something like this: (it would also work with malloc or any other dynamic allocation)
vector<Data> members;
vector<uint8_t> buffer;
Record myRecord;
buffer.resize(sizeof(Record) + members.size() * sizeof(Data));
myRecord = *(reinterpret_cast<Record*>(buffer.data());
myRecord.length = static_cast<uint32_t>(members.size());
// copy members to myRecord.contents
That works just fine. But now I need to have an interface that operates on batches of Record, and I have been trying to use an std::vector for this. Then problems start appearing, and I'm guessing it's because std::vector arranges all elements contiguously on memory, and since sizeof(Record) won't take into account the size of the contents (each vector element will hold only 4 bytes, instead of 4 bytes + size_of_contents * sizeof(Data)), the vector elements are actually sharing memory and then each element starts overwriting the contents of the previous element. Does that make sense?
If this really is the problem, I was wondering if there's any way to "force" the vector to allocate a specific size for each element (instead of whatever sizeof returns for the element's type). That way I could make sure that each vector element would have enough size. If that's not possible, is there an alternative solution? Maybe a different container that would allow me to do so? Please keep in mind that I do need to use the struct as it's defined (I would love to just replace the whole thing for a vector but unfortunately that's not possible)
Your principle problem is this:
myRecord = *(reinterpret_cast<Record*>(buffer.data());
That's simply overwriting the data in a stack variable. That does not change the address of myRecord to suddenly point to buffer.data(). Which means when you later do myRecord.contents[...] = ..., you're going to be trashing the stack.
What you almost certainly intended was:
Record *myRecord = (reinterpret_cast<Record*>(buffer.data());
Then you would have a pointer to memory managed by buffer, which would have sufficient storage for the myRecord->contents array.
You cannot treat Record like a value type. As far as C++'s object model is concerned, it's not a value type. It cannot be copied or moved like most C++ types. You can only manipulate it through a pointer/reference to the specific allocation you use here.
That being said, using a vector to manage the storage for your Record* like this is really weird. It'd be better to use a unique_ptr, since resizing the allocation would be a really bad idea.
std::unique_ptr<char[]> storage = new char[sizeof(Record) + (members.size() * sizeof(Data))];
This also prevents the system from initializing the memory, since you're going to overwrite it anyway.
I was wondering if there's any way to "force" the vector to allocate a specific size for each element (instead of whatever sizeof returns for the element's type).
No. vector manages a contiguous array of elements of the same type. And in C++, all objects of the same type have the same size.

Point to 3dimensional array in c++

I have searched on google but only found answers for single-dimension arrays.
I have a 3 dimension array storing data to be later processed by a function.
My array looks like this : levelcode[400][20][100]. It stores all the info that the decode level function needs. I get an stack overflow error immediately.
But how can i point to the entire array to get the values of it ( or how do i pass down the entire array? ) ?
I know i can technically call the function for each existing parameter but i think it would be faster and it would look better if the entire array was passed down or being used using a pointer of some sort.
How can i accomplish this?
I suggest you use a std::vector. It is basically a self managed grow-able array. It stores the data dynamically(heap) so you will be using the full system memory instead of the small bit of memory the program is given for automatic objects(stack). With your levelcode[400][20][100] you have 800,000 elements. if the array is of type int then you would more than likely need 3.2MB of space for the array. typically this is larger than than the space provided to the program and will cause a stack overflow
I would suggest you use single dimension vector and then you can use math to fake the 3 dimensions. This will make the data more cache friendly as multi-dimensional vectors do not have to have each dimension located right next to each other like a multi-dimensional array does.
So instead of having a
std::vector<std::vector<std::vector<some_type>>> name{DIM1, vector<vector<some_type>>{DIM2, vector<some_type>{DIM3}}};
and using it like
name[x][y][z]
We could have a
std::vector<some_type> name{DIM1 * DIM2 * DIM3};
and then you can access the elements with
name[x*DIM2*DIM3 + y*DIM3 + z]

Dynamic Array in C++ vs ArrayList in Java

I am new to C++. I am working on a problem from class. We must use Dynamic Arrays to read words from a file.
Here are my simple questions.
Does Dynamic Array imply the use of a pointer? Meaning we point at our new array made.
In Java, ArrayList can be created and size changes dynamically. But to me in C++, does using a dynamic array mean to set the size of the array to a large number and then dynamically allocate that array?
Is there no way to chop off the excess indexes from the dynamic array? So then delete the array at the end is the only choice I have in C++?
Thanks, pointers and dynamic arrays can only be used. Thank you.
Java ArrayList is only comparable to C++ Vector. A normal dynamic array does not change it's size at runtime so if you declare a dynamic int array in c++:
int *arr = new int[10];
The size of that array will remain at 10.
However if you use vector:
std::vector<int> arr(10);
Then when this vector is filled past 10 elements, the vector object automatically allocates more memory for itself.
So to answer your question, dynamic array implies making use of a pointer to keep track of the memory location where the heap-allocated array has been placed. But if you use vector, this is handled for you internally
I suppose dynamic array could refer either. Look at what you have to do and decide. Does it make scene to use an array where the size is fixed? I'm guessing that a vector would be the best here since you probably don't know ahead of time how large the file is.
std::vector<string> words;
Also just for your information the vector class simply stores a pointer to a dynamically allocated array. It creates a new one whenever you need more room, copies over the the data from the old array, and the deletes it. This all happens behind the scenes.
The C++ equivalent of a Java ArrayList is std::vector. You use the capitalized term "Dynamic Array" as if it has a specific meaning rather than the generic adjective "dynamic" applied to the concept "array". A "dynamic array" in C++ spec lingo is a local variable that has a fixed size, set when it is initialized/created, but that may get a different size each time the scope is entered (and the array recreated). Since it's local to a scope, its not too useful for storing stuff read from a file other than temporarily. C++ also has heap-allocated arrays which have their size set when created (as with a dynamic array), but which persist until explicitly deleted, which might be more useful. These are "dynamic" in the general adjective sense, but are not "dynamic arrays" in the spec sense.

Dynamically allocating an array of objects fails

I'm able to create a dynamically sized array of integers like this:
int *cacheL2 = new int[L2/B2];
and I'm also able to create an object of type Data like this:
Data one(12,12);
and now I want a dynamically sized array of Data:
Data * vlaObj = new Data[L2/B2];
but it does not work...
Also, if you can tell me how to get hashes working for c++ that would be great. I was looking for examples, but everything just says #include "hash_map" however when I try to use the library it cant seem to find any of them.
#include <vector>
// ...
std::vector<Data> v;
v.emplace_back( 12, 12 );
There is no reason to not use STL containers here. It is recommended to use std::vector instead of raw pointers:
#include <vector>
//...
std::vector<Data> vlaObj(L2/B2);
vlaObj.push_back(one)
Edit: BTW is there any chance that L2 or even B2 value can be 0?
One of the most probable reasons why Data* arr = new Data[len]; wouldn't work is because type Data has no default constructor, i.e. Data::Data().
But no matter whether Data has a default constructor or not, it's not a good idea to try to create an array like this anyway. Once you dynamically allocate it with new[] you commit yourself to take care of ugly memory management connect with it. It's much better idea to use one of STL containers such as std::vector (#include <vector> required) that will take care of memory management for you.
Then you have several options:
std::vector<Data> v; // option 1
v.reserve(len);
// in loop:
v.push_back(Data(x, y)); // there could be different values
std::vector<Data> v2(len); // option 2
std::vector<Data> v3(len, Data(12,12)); // option 3
First option will fit almost any situation. It prepares the chunk of memory big enough to hold len elements and then you can just fill v in convenient but still very efficient manner. Option 2 requires Data to have default constructor, which is solved by option 3 that uses your custom constructor to construct elements.
All mentioned options result in std::vector object with automatic storage duration being created. Note that all elements are stored in a continuous block of memory, so you can use &v[0] to initialize the pointer to its first element and work with it in a same way you would work with dynamically allocated array.

Create an N dimensional array, where N is determined at runtime (C++)

I'm encoding N-Dim image cubes into a different image format. I don't know the dimensions of the image until runtime and the library I'm using to read from the original image needs an N-dim array destination buffer as a parameter.
How can I declare such an array in C++? Thanks :)
The short answer is that you cannot declare such an array in C++. The dimensions of an array are part of the type (with a miscellaneous exception that sometimes the value of one of the dimensions can be unknown, for an extern array declaration). The number of dimensions is always part of the type, and the type must be known at compile time.
What you might be able to do instead is to use a "flat" array of appropriate size. For example, if you need a 3x3...x3 array then you can compute 3^n at runtime, dynamically allocate that many int (probably using a vector<int> for convenience), and you have memory with the same layout as an int[3][3]...[3]. You can refer to this memory via a void*.
I'm not certain that it's strictly legal in C++ to alias a flat array as a multi-dimensional array. But firstly the function you're calling might not actually alias it that way anyway given that it also doesn't know the dimension at compile-time. Secondly it will work in practice (if it doesn't, the function you're calling is either broken or else has some cunning way to deal with this that you should find out about and copy).
You can't use array in this case. Array is only for those data whose size and dimension are known at compile time. Try use an array of std::vector instead