Is it worth to use vector in case of making a map - c++

I have got a class that represents a 2D map with size 40x40.
I read some data from sensors and create this map with marking cells if my sensors found something and I set value of propablity of finding an obstacle. For example when I am find some obstacle in cell [52,22] I add to its value for example to 10 and add to surrounded cells value 5.
So each cell of this map should keep some little value(propably not bigger). So when a cell is marked three times by sensor, its value will be 30 and surronding cells will have 15.
And my question is, is it worth to use casual array or is it better to use vector even I do not sort this cells, dont remove them etc. I just set its value, and read it later?
Update:
Actually I have in my header file:
using cell = uint8_t;
class Grid {
private:
int xSize, ySize;
cell *cells;
public:
//some methods
}
In cpp :
using cell = uint8_t;
Grid::Grid(int xSize, int ySize) : xSize(xSize), ySize(ySize) {
cells = new cell[xSize * ySize];
for (int i = 0; i < xSize; i++) {
for (int j = 0; j < ySize; j++)
cells[x + y * xSize] = 0;
}
}
Grid::~Grid(void) {
delete cells;
}
inline cell* Grid::getCell(int x, int y) const{
return &cells[x + y * xSize];
}
Does it look fine?

I'd use std::array rather than std::vector.
For fixed size arrays you get the benefits of STL containers with the performance of 'naked' arrays.
http://en.cppreference.com/w/cpp/container/array

A static (C-style) array is possible in your case since the size in known at compile-time.
BUT. It may be interesting to have the data on the heap instead of the stack.
If the array is a global variable, it's ugly an bug-prone (avoid that when you can).
If the array is a local variable (let say, in your main() function), then a stack overflow may occur. Well, it's very unlikely for a 40*40 array of tiny things, but I'd prefer have my data on the heap, to keep things safe, clean, and future-proof.
So, IMHO you should definitely go for the vector, it's fast, clean and readable, and you don't have to worry about stack overflow, memory allocation, etc.
About your data. If you know your values are storable on a single byte, go for it !
An uint8_t (same as unsigned char) can store values from 0 to 255. If it's enough, use it.
using cell = uint8_t; // define a nice name for your data type
std::vector<cell> myMap;
size_t size = 40;
myMap.reserve(size*size);
side note: don't use new[]. Well, you can, but it has no advantages over a vector. You will probably only gain headaches handling memory manually.

Some advantages of using a std::vector is that it can be dynamically allocated (flexible size, can be resized during execution, etc) and can be passed/returned from a function. Since you have a fixed size 40x40 and you know you have one element int in every cell, I don't think it matters that much in your case and I would NOT suggest using a class object std::vector to process this simple task.
And here is a possible duplicate.

Related

Create an array dynamically in C++

I have to create a matrix with the width and height determined by two parameters obtained from the writing of a file. But, in some cases when the matrix is too big, I've got a segmentation fault. I think is probably because I'm creating the matrix in a static way, so I need to create it dynamically, but is here where my problem appears, because I don't know how to do it.
My code right now is this:
FILE * fp;
unsigned int width=0;
unsigned int height=0;
//Open the file. argv[4] parameter contains the file
fp=fopen (argv[4],"r");
//Go to the last position which indicates the size
fseek(fp, 0, SEEK_END);
//Return to the start:
rewind(fp);
//The value of the first 4 bytes represent the width
size_t return1 = fread(&width,4,1,fp);
//The value of the next 4 bytes represent the height
size_t return2 = fread(&height,4,1,fp);
//Matrix creation
if (return1 > 0 && return2 > 0) {
unsigned int matrix[width][height];
If you are having trouble figuring out how to create arrays dynamically, I would definitely advise you to use the vector class instead.
Vectors are dynamically allocated, and can scale.
std::vector<unsigned int> matrix{width * height};
Notice that I made the vector a single dimension, since it really simplifies a lot when allocating the vector.
To access a specific coordinate you could use:
matrix.at(w * width + h);
Where w and h are the coordinates, h should obviously be in the range 0 <= h < height.
If you were to dynamically allocate your array you would have to use the new operator, and then have to remember to clean up afterwards as well using the proper delete[] operator. There is a better answer for that here on Stack Overflow: How do I declare a 2d array in C++ using new?
Basically it would boil down to:
unsigned int** matrix = new unsigned int*[width];
for (int w = 0; w < width; ++w) {
matrix[w] = new unsigned int[height];
}
Then you would have to remember to delete the matrix again, using something like this:
for (int w = 0; w < width; ++w) {
delete [] matrix[w];
}
delete [] matrix;
So, in other words, I recommend that you use the vector class instead.
Of course with sufficiently large values of width and height, even vector can fail, simply because you are trying to allocate too much memory. If that is the case I think you should revisit your design, and reconsider how it is made.
Remember to include the vector header when using vectors:
#include <vector>
unsigned int matrix[width][height];
This has two problems.
Firstly, width and height are not compile time constants, which is required by the C++ standard for the size of the array. Therefore your program is ill-formed. Your compiler might support variable length arrays (VLA) as a language extension, so it might work with your compiler anyway.
Secondly, VLA may be stored on the stack, and stack space is limited. Indeed, with a large array you can easily overflow the stack. You are correct, that you'll need to allocate the array dynamically. Both because the size is dynamic (assuming you want your program to work with other, standard compliant compilers that do not support VLA) and because it prevents the stack from overflowing.
The simplest way to create a dynamic array is std::vector. Tommy Andersen goes more into depth on how to use vectors in his answer.

Accessing methods of objects held in multidimensional vectors of unique_ptr's

I have a 2 dimensional structure of objects initialized as thus:
std::vector<std::shared_ptr<tile> > appearance;
for (int x = 0; x < building_data.x_width; x++)
{
appearance.push_back
(std::shared_ptr<tile>(new tile[building_data.y_length]));
}
now, as far as I can figure out, the only way to access a member function of a tile in this is to use
appearance.at(x).get()[y].member_function()
which is confusing and cumbersome, and I feel like I'm missing something.
Previously, I had used tile** for the same structure, and the syntax of
tile[x][y] was nice but the raw pointers were a headache.
So, is there a better way access functions of an object held in an array, where the first element in the array is pointed to by a smart pointer held in a vector? Wordy but its the best I have.
You can use the -> operator to access members of the object managed by the shared_ptr. It's the same syntax you use with raw pointers.
However, you're going to run into problems with delete as mentioned in Dantez's answer.
Also, it looks like you're building some sort of board of tiles, perhaps for a game? Have you considered replacing the multidimensional array with with a 1D vector and some accessor functions?
// board_width and height should be integers
std::vector<Tile> board;
board.reserve(board_width * board_height);
for (unsigned y_axis = 0; y_axis < board_height; ++y_axis)
{
for (unsigned x_axis = 0; x_axis < board_width; ++x_axis)
{
board.push_back(Tile());
}
}
...
vec2 index_to_coords(unsigned index)
{
return vec2(index % board_width, index / board_width);
}
...
unsigned coords_to_index(const vec2& coords)
{
return (static_cast<unsigned>(coords.y) * board_width) + static_cast<unsigned>(coords.x);
}
First of all, shared_ptr is not designed to work with arrays. When there is no more references, it calls delete instead of delete[] which results in undefined behaviour if managed object is an array. You can read about it here.
As for accessing shared_ptr object, you can use operator* to dereference it.
Also, if you know vector's final size, you may want to reserve some space to avoid reallocation.
I agree with Fibbles, but have an alternate idea to provide. Fibble's approach is actually quite common even in C, because multidimensional structures (matrices) are just much easier that way.
However, if you do insist on the two dimensional concept, you can nest vectors. Consider:
typedef std::vector< tile > TileRow;
typedef std::vector< TileRow > Tiles;
At first, this may be a bit confusing, so to be clear that creates:
std::vector< std::vector< tile > > t;
However, with the typedef, thats
Tiles t;
Now, that's empty. To use it you'd need to push in some rows, and for each row push in some columns. You might not like that, so...you can use the assign function to set some rows. If, for example, you needed a matrix of 10 rows by 10 columns, you might
t.assign( 10, TileRow( 10, tile() ) );
This assume tile has a default constructor, pushing 10 rows of TileRow, each with 10 columns of default constructed tiles.
Now, t[ 1 ] returns a reference to the row 1. As such, t[ 1 ][ 1 ] is a reference to the tile at location 1,1, much like an array.
Yet, now you have no allocation/deallocation issues.
Something similar can be done with std::array, even better.
typedef std::array< tile, 10 > TileRow;
typedef std::array< TileRow, 10 > Tiles;
Tiles t;
At which point, t is ready with default initialized tiles.

Incrementally dynamic allocation of memory in C/C++

I have a for-loop that needs to incrementally add columns to a matrix. The size of the rows is known before entering the for-loop, but the size of the columns varies depending on some condition. Following code illustrates the situation:
N = getFeatureVectorSize();
float **fmat; // N rows, dynamic number of cols
for(size_t i = 0; i < getNoObjects(); i++)
{
if(Object[i] == TARGET_OBJECT)
{
float *fv = new float[N];
getObjectFeatureVector(fv);
// How to add fv to fmat?
}
}
Edit 1 This is how I temporary solved my problem:
N = getFeatureVectorSize();
float *fv = new float[N];
float *fmat = NULL;
int col_counter = 0;
for(size_t i = 0; i < getNoObjects(); i++)
{
if(Object[i] == TARGET_OBJECT)
{
getObjectFeatureVector(fv);
fmat = (float *) realloc(fmat, (col_counter+1)*N*sizeof(float));
for(int r=0; r<N; r++) fmat[col_counter*N+r] = fv[r];
col_counter++;
}
}
delete [] fv;
free(fmat);
However, I'm still looking for a way to incrementally allocate memory of a two-dimensional array in C/C++.
To answer your original question
// How to add fv to fmat?
When you use float **fmat you are declaring a pointer to [an array of] pointers. Therefore you have to allocate (and free!) that array before you can use it. Think of it as the row pointer holder:
float **fmat = new float*[N];
Then in your loop you simply do
fmat[i] = fv;
However I suggest you look at the std::vector approach since it won't be significantly slower and will spare you from all those new and delete.
better - use boost::MultiArray as in the top answer here :
How do I best handle dynamic multi-dimensional arrays in C/C++?
trying to dynamically allocate your own matrix type is pain you do not need.
Alternatively - as a low-tech, quick and dirty solution, use a vector of vectors, like this :
C++ vector of vectors
If you want to do this without fancy data structures, you should declare fmat as an array of size N of pointers. For each column, you'll probably have to just guess at a reasonable size to start with. Dynamically allocate an array of that size of floats, and set the appropriate element of fmat to point at that array. If you run out of space (as in, there are more floats to be added to that column), try allocating a new array of twice the previous size. Change the appropriate element of fmat to point to the new array and deallocate the old one.
This technique is a bit ugly and can cause many allocations/deallocations if your predictions aren't good, but I've used it before. If you need dynamic array expansion without using someone else's data structures, this is about as good as you can get.
To elaborate the std::vector approach, this is how it would look like:
// initialize
N = getFeatureVectorSize();
vector<vector<float>> fmat(N);
Now the loop looks the same, you access the rows by saying fmat[i], however there is no pointer to a float. You simply call fmat[i].resize(row_len) to set the size and then assign to it using fmat[i][z] = 1.23.
In your solution I suggest you make getObjectFeatureVector return a vector<float>, so you can just say fmat[i] = getObjectFeatureVector();. Thanks to the C++11 move constructors this will be just as fast as assigning the pointers. Also this solution will solve the problem of getObjectFeatureVector not knowing the size of the array.
Edit: As I understand you don't know the number of columns. No problem:
deque<vector<float>> fmat();
Given this function:
std::vector<float> getObjectFeatureVector();
This is how you add another column:
fmat.push_back(getObjectFeatureVector());
The number of columns is fmat.size() and the number of rows in a column is fmat[i].size().

What's the proper way to declare and initialize a (large) two dimensional object array in c++?

I need to create a large two dimensional array of objects. I've read some related questions on this site and others regarding multi_array, matrix, vector, etc, but haven't been able to put it together. If you recommend using one of those, please go ahead and translate the code below.
Some considerations:
The array is somewhat large (1300 x 1372).
I might be working with more than one of these at a time.
I'll have to pass it to a function at some point.
Speed is a large factor.
The two approaches that I thought of were:
Pixel pixelArray[1300][1372];
for(int i=0; i<1300; i++) {
for(int j=0; j<1372; j++) {
pixelArray[i][j].setOn(true);
...
}
}
and
Pixel* pixelArray[1300][1372];
for(int i=0; i<1300; i++) {
for(int j=0; j<1372; j++) {
pixelArray[i][j] = new Pixel();
pixelArray[i][j]->setOn(true);
...
}
}
What's the right approach/syntax here?
Edit:
Several answers have assumed Pixel is small - I left out details about Pixel for convenience, but it's not small/trivial. It has ~20 data members and ~16 member functions.
Your first approach allocates everything on stack, which is otherwise fine, but leads to stack overflow when you try to allocate too much stack. The limit is usually around 8 megabytes on modern OSes, so that allocating arrays of 1300 * 1372 elements on stack is not an option.
Your second approach allocates 1300 * 1372 elements on heap, which is a tremendous load for the allocator, which holds multiple linked lists to chunks of allocted and free memory. Also a bad idea, especially since Pixel seems to be rather small.
What I would do is this:
Pixel* pixelArray = new Pixel[1300 * 1372];
for(int i=0; i<1300; i++) {
for(int j=0; j<1372; j++) {
pixelArray[i * 1372 + j].setOn(true);
...
}
}
This way you allocate one large chunk of memory on heap. Stack is happy and so is the heap allocator.
If you want to pass it to a function, I'd vote against using simple arrays. Consider:
void doWork(Pixel array[][]);
This does not contain any size information. You could pass the size info via separate arguments, but I'd rather use something like std::vector<Pixel>. Of course, this requires that you define an addressing convention (row-major or column-major).
An alternative is std::vector<std::vector<Pixel> >, where each level of vectors is one array dimension. Advantage: The double subscript like in pixelArray[x][y] works, but the creation of such a structure is tedious, copying is more expensive because it happens per contained vector instance instead of with a simple memcpy, and the vectors contained in the top-level vector must not necessarily have the same size.
These are basically your options using the Standard Library. The right solution would be something like std::vector with two dimensions. Numerical libraries and image manipulation libraries come to mind, but matrix and image classes are most likely limited to primitive data types in their elements.
EDIT: Forgot to make it clear that everything above is only arguments. In the end, your personal taste and the context will have to be taken into account. If you're on your own in the project, vector plus defined and documented addressing convention should be good enough. But if you're in a team, and it's likely that someone will disregard the documented convention, the cascaded vector-in-vector structure is probably better because the tedious parts can be implemented by helper functions.
I'm not sure how complicated your Pixel data type is, but maybe something like this will work for you?:
std::fill(array, array+100, 42); // sets every value in the array to 42
Reference:
Initialization of a normal array with one default value
Check out Boost's Generic Image Library.
gray8_image_t pixelArray;
pixelArray.recreate(1300,1372);
for(gray8_image_t::iterator pIt = pixelArray.begin(); pIt != pixelArray.end(); pIt++) {
*pIt = 1;
}
My personal peference would be to use std::vector
typedef std::vector<Pixel> PixelRow;
typedef std::vector<PixelRow> PixelMatrix;
PixelMatrix pixelArray(1300, PixelRow(1372, Pixel(true)));
// ^^^^ ^^^^ ^^^^^^^^^^^
// Size 1 Size 2 default Value
While I wouldn't necessarily make this a struct, this demonstrates how I would approach storing and accessing the data. If Pixel is rather large, you may want to use a std::deque instead.
struct Pixel2D {
Pixel2D (size_t rsz_, size_t csz_) : data(rsz_*csz_), rsz(rsz_), csz(csz_) {
for (size_t r = 0; r < rsz; r++)
for (size_t c = 0; c < csz; c++)
at(r, c).setOn(true);
}
Pixel &at(size_t row, size_t col) {return data.at(row*csz+col);}
std::vector<Pixel> data;
size_t rsz;
size_t csz;
};

pointer arithmetic on vectors in c++

i have a std::vector, namely
vector<vector<vector> > > mdata;
i want pass data from my mdata vector to the GSL function
gsl_spline_init(gsl_spline * spline, const double xa[], const double ya[], size_t size);
as ya. i already figured out that i can do things like
gsl_spline_init(spline, &(mgrid.front()), &(mdata[i][j][k].front()), mgrid.size());
this is fine if i want to pass the data from mdata for fixed i,j to gsl_spline_init().
however, now i would need to pass along the first dimension of mdata, so for fixed j,k.
i know that for any two fixed indices, all vectors along the remaining dimensions have the same length, so my vector is a 'regular cube'. so the offset between all the values i need should be the same.
of course i could create a temporary vector
int j = 123;
int k = 321;
vector<double> tmp;
for (int i = 0: i < mdata.size(); i++)
tmp.push_back(mdata[i][j][k]);
gsl_spline_init(spline, &(mgrid.front()), &(tmp.front()), mgrid.size());
but this seems too complicated. perhaps there is a way to achieve my goal with pointer arithmetic?
any help is greatly appreciated :)
You really can't do that without redesigning the array consumer function gsl_spline_init() - it relies on the data passed being a contiguous block of data. This is not the case with you three-level vector - not only it is a cube but also each level has a separate buffer allocated on heap.
This can't be done. Not only with vectors, but even with plain arrays only the last dimension is a contiguous block of data. If gsl_spline_init took an iterator instead of array, you could try to craft some functor to choose appropriate data but I'm not sure it's worth trying. No pointer arithmetic can help you.