I have a class called Grid that declares a vector of vectors like this:
typedef vector<int> row;
typedef vector<row> myMatrix;
myMatrix sudoku_;
The constructor looks like this:
grid::grid() : sudoku_(9,9)
{
}
As you can see, the constructor is initializing it to be a 9x9 grid. How can I make it work so that the user is asked for a number, say n, and the grid is initialized n x n ?
vector has a constructor that allows you to initialize it to a certain size with copies of a given value:
grid::grid(size_t w, size_t h) : sudoku_(w, row(h)) {}
if you can, do not use vector.
Use this instead http://www.boost.org/doc/libs/1_42_0/libs/multi_array/doc/user.html
#gf has the absolute right answer for the question, but I'd question the use of vector here (rare for me). In the case of a sudoku grid the structure is fixed size, so you don't win by having easy dynamic allocation. By using a vector of 9 vectors, you have ten populated vector objects. Each one of these has at least one dynamic allocation, so ten calls to new. On top of that, on the implementation of std::vector I am most familiar with the object is 12 bytes (3 32-bit pointers), plus the heap allocation overhead. All of that to deal with a structure which can comfortably be represented in less than 100 bytes is overkill.
Related
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.
I have in my class 2 const int variables:
const int m_width;
const int m_height;
In my constructor, I have set the variables and I want to create a 2D array with exactly this size that will be passed by value from the player. I am trying to make a TicTacToe game. I need the input of the user to determine the size of the playing field(in this case the width and height of it). How do I dynamically declare a 2D array in my situation?
It is a common misconception that 2-dimensional matrices should be supported by two-dimensional storage. People often try to use vectors of vectors or other techniques, and this comes at a cost, both performance and code maintainability.
This is not needed. In fact, perfect two-dimensional matrix is a single std::vector, where every row is packed one after each another. Such a vector has a size of of M * N, where M and N are matrix height and width. To access the element at location X, Y, you do v[K], where K is calculated as X * N + Y.
C++ doesn't provide a standard dynamic 2D array container.
What you can do (if you don't want to write your own full implementation) is use an std::vector of std::vectors instead.
It's not exactly the same thing (provides you with an extra degree of freedom: rows can be of different length) but unless you're working in an extremely constrained environment (or need an extremely optimized solution) the extra cost is not big.
Supposing your elements needs to be integers the code to initialize a 2d array can be for example:
std::vector<std::vector<int>> board(rows, std::vector<int>(cols));
PS: A few years ago I wrote a class here to implement a simple 2D array as an answer to an SO question... you can find it here.
According to that question, I'm more and more worried about the management of the memory in my project, and my program would crash when there is somewhere a conflict in one of the array memories.
The different answers to this posted question have converged to the fact that I would change my arrays to Vectors and some of my arrays are defined as below:
#define Nb 50
int position[Nb];
double indication[Nb];
double sum[Nb];
how to change each one of them to
std::vector
std::list?
Can we manipulate / process them when changing their declaration (organizing them in ascending order for example or overwriting one of the values) ?
You are using fixed size arrays,
#define Nb 50
int position[Nb];
the modern C++ alternative to these is std::array, not std::vector:
std::array<int, 50> position;
std::vector is a dynamically sized array, whose size can be determined at runtime and can change after construction.
int n;
std::cin >> n;
std::vector<int> v(n); // vector has n value constructed ints
v.push_back(42); // v has n+1 ints now.
C++14 offers std::dynarray, which is a dynamically sized array, whose size can be determined at runtime but cannot be changed after construction.
The Syntax is as follows:
#define Nb 50
std::vector<int> position(Nb); // create std::vector holding ints, Initial size is 50
You should also refrain from using #define, but rather use const, this is more C++:
const int Nb = 50; //maybe wrap Nb in a namespace
std::vector<int> position(Nb);
See vector and its constructors.
Need for two dimensional array of objects that could be something like:
myContainer<myObject*> *a = new myArray<myObject*>( 20, 20 ); // passing int's as width & height
later accessing values would be done with methods such as:
mylist<myObject*> getRow( int );
mylist<myObject*> getColumn( int );
mylist<myObject*> getDiagonalRow( int );
implementations of those could be something like:
myList<myObject*> myContainer::getRow( int a ){
if( a < 0 && a>=this->height )
return;
myList<myObject*> hlp;
for( int i=0; i<this->width; i++)
hlp.append( this->arr[a][i] );
return hlp; // returns a copy. Could also be a pointer if created with new.
}
Other methods could follow similar lines, ie. creating a list object and filling it with what was requested.
My questions: Can anyone think of elegant way to create a container class I'm describing here. Which could for example avoid creating and filling of list-objects but still maintaining the abstraction and/or usability. Or please advice if I have missed something in STL etc. that has something like this.
STL has the valarray container which can be viewed as row and columns using slices, but you have to do it manually or wrap it into a wrapper class. Also the slices represents the values of the valarray (they are not a copy), but it is designed to be used with numbers and to be a bit optimized, it doesn't have any iterator and cannot be grown. it's doesn't follow the usual STL container concept. but it can still be used as a quick and dirty workaround if you can't use boost.
std::valarray<float> array(16);
// we can view it as a 4x4 matrix.
// this represents the first line
array[std::slice(0,4,1)];
// and the second column
array[std::slice(1,4,4)];
// you cannot use the sliced array directly. they don't
// have operator[], but they have operator=(valarray), and
// valarray has a constructor that takes sliced arrays as input.
What is the speed you are aiming for?
I can image to get a getRow() and getColumn() and getDiagonal()
in constant time when you handle with something list-like in the background.e.g. vector.
(if you just return a pointer)
Should the container grow or is the size fixed after the initialization?
If your container size is m and n you can store m std::vectors of size n,
n std::vectors of size m, and m+n std::vectors of different sizes.
Describing the rows, coloumns, and diagonals.
Then the get methods are easy to implement and in a at() or [] method/operator
three entries are to be changed.
I want to implement a function that gets as a parameter a dimension "n" of an array of integers. This function also gets values "k_1, k_2, ..., k_n" defining the size of the array. Then this function will fill this n-dimensional array.
How do I implement this efficiently with C++?
For example for n = 3 I would use
vector < vector < vector < int > > > array;
But I don't know the dimension at compile time.
Use a one-dimensional array, and fake the other dimensions using multiplication of offsets for indexing, and you can pass the dimension sizes in by vector, i.e.
std::vector<int> create_md_array(const std::vector<int> & dimensions)
{
int size = std::accumulate(dimensions.begin(), dimensions.end(), 1, std::multiplies<int>());
return std::vector<int>(size);
}
You have a couple of choices. You can implement it yourself, basically multiplying the coordinates by the sizes to linearize the multi-dimensional address, and just have a simple std::vector<whatever> to hold the data.
Alternatively, you could use std::valarray and friends to accomplish the same. It has a set of classes that are specifically intended for the kind of situation you describe -- but they're used so rarely that almost nobody understands them. Writing the code yourself stands a good chance of being easier for most people to read and understand.