Multidimensional Containers in C++ - c++

Is there any library provide a multidimensional container to use like vector<>?
I would like to see something like:
TwoD<object_class_name> D2;
ThreeD<object_class_name> D3;
and the object_class_name could be any object instead of only the builtin types.
so I can use the object like
D2[i][j]
D3[i,j,k] or D3(i,j,k)
or similar
Thanks.

If c++11, a possible solution is using which allows aliasing of a template:
template <typename T>
using TwoD = std::vector<std::vector<T>>;
template <typename T>
using ThreeD = std::vector<std::vector<std::vector<T>>>;
usage:
TwoD<int> t2ints;
TwoD<std::string> t2strings;
ThreeD<int> t3ints;
ThreeD<std::string> t3strings;

boost::multi_array can do that.
2D array example:
boost::multi_array<float, 2> float2D(boost::extents[5][10]);
float2D[0][0] = 1.0f;
3D array example:
boost::multi_array<float, 3> float3D(boost::extents[5][10][20]);
float2D[0][0][0] = 1.0f;
The stored type can be a class or struct as well as a primitive type, and the memory used will be contiguous.

YOu could do something like this:
std::vector<std::vector<someType> > TwoDVector;
Or a two dimensional array like these:
someType** TwoDArrayPointer;
someType TwoDArray[size][size2];

I don't like vector<vector> because each row gets its own separately allocated memory block on the heap. This causes two problems:
Iterating over all elements of the array will have very poor cache performance compared to a contiguous 2D array.
You can't pass the array into a function that wants a 1D array. For example, a lot of imaging libraries only want a char * for image data.
Therefore, I would suggest writing your own 2D array template. It's a pretty simple task. Or you can use my public domain code at github.com/jpreiss/array2d .
Also note: you can't overload operator[] with a function that takes more than one parameter. You can overload operator() for 2D indexing.

You can use vector.
// Create
vector< vector<int> > vec(4, vector<int>(4));
// Write
vec[2][3] = 10;
// Read
int a = vec[2][3];

Related

iterate over std::vector of std::vector [duplicate]

I'm trying to pass a variable of type vector<vector<double> > to a function F(double ** mat, int m, int n). The F function comes from another lib so I have no option of changing it. Can someone give me some hints on this? Thanks.
vector<vector<double>> and double** are quite different types. But it is possible to feed this function with the help of another vector that stores some double pointers:
#include <vector>
void your_function(double** mat, int m, int n) {}
int main() {
std::vector<std::vector<double>> thing = ...;
std::vector<double*> ptrs;
for (auto& vec : thing) {
// ^ very important to avoid `vec` being
// a temporary copy of a `thing` element.
ptrs.push_back(vec.data());
}
your_function(ptrs.data(), thing.size(), thing[0].size());
}
One of the reasons this works is because std::vector guarantees that all the elements are stored consecutivly in memory.
If possible, consider changing the signature of your function. Usually, matrices are layed out linearly in memory. This means, accessing a matrix element can be done with some base pointer p of type double* for the top left coefficient and some computed linear index based on row and columns like p[row*row_step+col*col_step] where row_step and col_step are layout-dependent offsets. The standard library doesn't really offer any help with these sorts of data structures. But you could try using Boost's multi_array or GSL's multi_span to help with this.
The way I see it, you need to convert your vector<vector<double> > to the correct data type, copying all the values into a nested array in the process
A vector is organised in a completely different way than an array, so even if you could force the data types to match, it still wouldn't work.
Unfortunately, my C++ experience lies a couple of years back, so I can't give you a concrete example here.
Vector< Vector< double> > is not nearly the same as a double pointer to m. From the looks of it, m is assumed to be a 2-dimensional array while the vector is could be stored jagged and is not necessarily adjacent in memory. If you want to pass it in, you need to copy the vector values into a temp 2dim double array as pass that value in instead.

create a Dynamic std::array of std::array

My task requires me to create an array of arrays to store some data , where the number of row is fixed and the columns are to be decided at run-time.
If I was using a simple int array then this would've been a simple task but because I have to use std::array , I am lost .
My attempt so far
#include<iostream>
#include<array>
using std::array;
int main(){
array<array<int,1>*,3> x;
for(size_t i=0;i<3;i++)
{
x[i][0]=array<int,3>;
}
}
which leads to the error
array1.cpp:12:29: error: expected '(' for function-style cast or type
construction
x[i][0]=array;
~~~~~~~~~~~~^ 1 error generated.
when using clang++
I have read that an std::array is equivalent to a normal array ,
I know i can use vectors but since i know how many rows i have from the beginning , I feel it to be a waste to use vectors , while I would love the added functionality of std::array when compared to a traditional array. How do I implement this .
std::array<std::vector<int>,3> is the type you want.
std::vector is a dynamicly sized array.
int main(){
std::array<std::vector<int>,3> x;
for(std::size_t i=0;i<3;i++)
{
x[i]=std::vector<int>(22);
}
}
this creates a 3 "major" element array of 22 "minor" size.
Note that column-major and row-major (which is first and which is second) is a matter of convention. So std::vector<std::array<3,int>> is another equally valid interpretation of the requirements.
If you are banned from using std::vector, you will have to figure out an alternative solution, possibly rolling your own. I'd advise against unique_ptr<int[]> (or worse, raw pointers) as they don't store the size of the element.
A std::array< std::array< cannnot be dynamic in either dimension. std::array is fixed size.
My task requires me to create an array of arrays to store some data , where the number of row is fixed and the columns are to be decided at run-time.
It sounds like your task requires using a matrix class. Like boost::numeric::ublas::matrix.
The benefit of using a matrix class is that internally it uses one dynamic array to minimize storage overhead.
If you are coding this as an exercise create your own matrix class. Otherwise use an existing one.

1D Vector to Multi-dimensional array / Vector

I have a 1D dimensional vector of floats I just read in from a file.
std::vector<float> result(s.size() / sizeof(float));
I want to use this data like this
myTable[rl][gl][bl][0];
So is there any easy way to convert my 1D vector to a multidimensional vector or multidimensional array that is simple?
float myTable[100][10][20][30];
vector<vector<vector<vector<int> >>> myTable;
Where I can still easily use the indexing that is setup all over the code.
and not have to convert it to a 1D access like : myTable[indexmathhere]
I wouldn't actually rewrite the data, unless you have cache requirements (though we don't know anything about the layout of your data).
Store the vector inside a class, and write an accessor function that takes four index arguments and performs the necessary arithmetic to flatten them into the single vector index.
class MyMatrix
{
std::vector<float> result;
public:
float at(int r, int g, int b, int a) const
{
return result[r+W*g+W*H*b+W*H*D*a]; // or whatevs
}
};
You could even write some operator() overloads, but you'd need three proxy types to get four dimensions of indexing out of that.
If you have fixed size array you probably should use std::array.
Something like it is in this question: Multidimensional std::array
Unfortunately, there is no oneliner to put your data into this array, you need to do it manually.

How to store an unknown number of elements in an array C++

Sorry if the title is not clear but I ll explain now my problem. I am new in C++.
I have created a class in C++. Instances of that class are the input of the program and they have to be stored in an array to perform the calculations. The problem is that the number of instances of that class that have to be defined by the user is fixed for a single run but can vary from run to run. Here an example:
#include <<blablah>blahblah>
int main()
{
int number_of_instances = 3;
MyClass first_instance(one_parameter_1, another_parameter_1);
MyClass second_instance(one_parameter_2, another_parameter_2);
MyClass third_instance(one_parameter_3, another_parameter_3);
///////////////////
NOW I HAVE TO STORE ALL THREE IN AN ARRAY LIKE
MyClass array[number_of_instances] = {first_instance, second_instance, third_instance};
THE PROBLEM IS THAT I DO NOT KNOW BEFORE HAND HOW MANY OF THEM ARE THE USER IS GOING TO INPUT
///////////////////
performCalculations(array);
return 0;
}
Thanks a lot in advance.
The typical C++ solution is to use a vector.
vector<MyClass> v;
v.push_back(first_instance); //add an already instantiated object to the end of the vector
v.push_back(second_instance);
v.push_back(third_instance);
You won't have to worry about memory management and you are able to access the vector like you would a normal array:
v[0].classMember
You can also add items to the vector in a loop if needed like so:
for(int i = 0; i < 5; i++){
v.push_back( MyClass(i, param2) );
}
And all the objects will be destructed when the vector goes out of scope if you're storing the objects directly in the vector.
One of the downsides to storing the objects directly in the vector is passing the vector as a parameter to a function. This will be a slow operation since the vector (and all the objects it holds) will have to be copied.
If you know the number of instances before you read them all in then you can allocate an array on the heap using new[]. (Don't forget to delete[] them when you've finished.) Note that this requires that the object have a default constructor.
you should use std::vector in this case rather than a built-in array.
#include <vector>
...
std::vector<MyClass> v = {first_instance, second_instance, third_instance};
...
v.push_back(fourth_instance);
If you don't know how many elements the array will contain, I would use a std::vector instead of a plain array as the vector will grow to accommodate the additional elements.
What you want is the Vector class from the standard template library, it behaves like an array but it will re-size itself if you fill it's internal allocation. If you do not need random access to it (i.e. use the [] opperator) you may want to use the List class instead. If you use List you will need to create an enumerator to step through it.
use std::vector<MyClass>, vector template can be found in <vector> header. YOu must learn a little bit to code well, before coding use any of online available c++ FAQs

A generic method to set the length of a dynamic array of arbitrary type in c++

I am doing a project converting some Pascal (Delphi) code to C++ and would like to write a function that is roughly equivalent to the Pascal "SetLength" method. This takes a reference to a dynamic array, as well as a length and allocates the memory and returns the reference.
In C++ I was thinking of something along the lines of
void* setlength(void* pp, int array_size, int pointer_size, int target_size, ....) {
void * p;
// Code to allocate memory here via malloc/new
// something like: p = reinterpret_cast<typeid(pp)>(p);
// p=(target_size) malloc(array_size);
return p;
}
My question is this: is there a way to pass the pointer type to a function like this and to successfully allocate the memory (perhaps via a typeid parameter?)? Can I use
<reinterpret_cast>
somehow? The ultimate aim would be something like the following in terms of usage:
float*** p;
p=setlength(100,sizeof(float***),sizeof(float**),.....);
class B;
B** cp;
cp=setlength(100,sizeof(B**),sizeof(B*),.....);
Any help would be most welcome. I am aware my suggested code is all wrong, but wanted to convey the general idea. Thanks.
Use std::vector instead of raw arrays.
Then you can simply call its resize() member method.
And make the function a template to handle arbitrary types:
If you want to use your function, it could look something like this:
template <typename T>
std::vector<T>& setlength(std::vector<T>& v, int new_size) {
v.resize(new_size);
return v;
}
But now it's so simple you might want to eliminate the function entirely and just call resize to begin with.
I'm not entirely sure what you're trying to do with the triple-pointers in your example, but it looks like you don't want to resize though, you want to initialize to a certain size, which can be done with the vector constructor:
std::vector<float>v(100);
If you wanted to do it literally, you would do it like this:
template <typename T>
T* SetLength(T* arr, size_t len) {
return static_cast<T*>(realloc(arr, sizeof(T) * len));
}
Note that the array must have been allocated with malloc or calloc. Also note that this does not actually resize the memory—it deallocates the memory and reallocates memory of the appropriate size. If there were any other pointers to the array being passed in, they will be invalid afterwards.
You're really better off using a more idiomatic C++ solution, like std::vector.
For a multidimensional array, probably the best option would be to use boost's multi_array library:
typedef boost::multi_array<float, 3> array_type;
array_type p(boost::extents[100][100][100]); // make an 100x100x100 array of floats
p[1][2][3] = 4.2;
This lets you completely abstract away the allocation and details of setting up the multidimensional array. Plus, because it uses linear storage, you get the efficiency benefits of linear storage with the ease of access of indirections.
Failing that, you have three other major options.
The most C++-y option without using external libraries would be to use a STL container:
std::vector<float **> p;
p.resize(100);
As with multi_array, p will then automatically be freed when it goes out of scope. You can get the vector bounds with p.size(). However the vector will only handle one dimension for you, so you'll end up doing nested vectors (ick!).
You can also use new directly:
float ***p = new float**[100];
To deallocate:
delete [] p;
This has all the disadvantages of std::vector, plus it won't free it for you, and you can't get the size later.
The above three methods will all throw an exception of type std::bad_alloc if they fail to allocate enough memory.
Finally, for completeness, there's the C route, with calloc():
float ***p = (float ***)calloc(100, sizeof(*p));
To free:
free((void*)p);
This comes from C and is a bit uglier with all the casts. For C++ classes it will not call the constructors for you, either. Also, there's no checking that the sizeof in the argument is consistent with the cast.
If calloc() fails to allocate memory it will return NULL; you'll need to check for this and handle it.
To do this the C++ way:
1) As jalf stated, prefer std::vector if you can
2) Don't do void* p. Prefer instead to make your function a template of type T.
The new operator itself is essentially what you are asking for, with the exception that to appropriately allocate for double/triple pointers you must do something along the following lines:
float** data = new float*[size_of_dimension_1];
for ( size_t i=0 ; i<size_of_dimension_1 ; ++i )
data[i] = new float[size_of_dimension_2];
...
// to delete:
for ( size_t i=0 ; i<size_of_dimension_1 ; ++i )
delete [] data[i];
delete [] data;
Edit: I would suggest using one of the many C++ math/matrix libraries out there. I would suggest uBlas.