C++ vector of fixed size vecors - c++

How can I declare vector of fixed size vectors in C++?
For example:
vector of vectors with N elements.
Not this:
vector<vector<int> > v(N) //declares vector of N vectors

std::array is your friend here.
http://en.cppreference.com/w/cpp/container/array
For instance, to declare vector of vectors with N elements, you can
typedef std::array<int, N> N_array;
Then use
std::vector<N_array>

You could use std::array:
std::array<int, 10> myNumbers;
The only down side to this is you can't see how many "active" elements there are, since you don't push/emplace back. You use it like an ordinary( but safe ) array.

If you wish to have vector of fixed size, most likely you don't need one! Use std::array instead.
But still you insist to have one..
vector<vector<int> > vecOfVec(NumberOfVectors);
for ( int i = 0 ; i < NumberOfVectors; i++ )
vecOfVec[i].resize(NumberOfElementsInVector);

Related

Size of array of std::vector

I would like to check the size() or number of rows in an array of std::vector().
I have vector like
std::vector<int> vec[3];
vec.size() does not work with the above vector declaration.
As for why vec.size() does not work, it's because vec is not a vector, it's an array (of vectors), and arrays in C++ are not objects (in the OOP sense that they are not instances of a class) and therefore have no member functions.
If you want to get the result 3 when doing vec.size() then you either have to use e.g. std::array:
std::array<std::vector<int>, 3> vec;
std::cout << "vec.size() = " << vec.size() << '\n'; // Will output 3
Or if you don't have std::array then use a vector of vectors and set the size by calling the correct constructor:
std::vector<std::vector<int>> vec(3);
std::cout << "vec.size() = " << vec.size() << '\n'; // Will output 3
There's nothing inherent in std::vector<int> vec[3]; to say where the first or second indexing operation constitutes "rows" vs. "columns" - it's all a matter of your own perspective as a programmer. That said, if you consider this to have 3 rows, you can retrieve that number using...
std::extent<decltype(vec)>::value
...for which you'll need to #include <type_traits>. See here.
Anyway, std::array<> is specifically designed to provide a better, more consistent interface - and will already be familiar from std::vector:
std::array<std::vector<int>, 3> vec;
...use vec.size()...
(Consistency is particularly important if you want templated code to handle both vectors and arrays.)
Try
int Nrows = 3;
int Ncols = 4
std::vector<std::vector<int>> vec(Nrows);
for(int k=0;k<Nrows;k++)
vec[k].resize(Ncols);
...
auto Nrows = vec.size();
auto Ncols = (Nrows > 0 ? vec[0].size() : 0);
Either use sizeof(vec[0])/sizeof(vec) or sizeof(vec)/sizeof(vector<int>)

Can I have a variably modified vector in c++?

Is there any way to do this:
std::vector<char[foo]> bar;
I need ONE contiguous array of char[foo] but I don't know the length until runtime. I need to be able to add blocks of char[foo] dynamically.
I need the inner array to be exactly the right size, so if foo was 3:
[ [1, 2, 3] [4, 5, 6] ... [x, y, z] ]
I could implement it myself but don't want to reinvent the wheel.
I'd suggest using
std::vector< std::vector< char > >
std::vector's internal memory is continuous.
Well, after a while, it appeared, that the whole memory must be continuous, which changes everything..
For this case, you can use directly std::vector< char >::insert( pos, begin, end ) to insert whole "chunks".
Something like: (I didn't test it, but you'll get the idea)
std::vector< char > bar;
// ..
{
std::vector< char > buff( foo );
// fill buff
bar.insert( bar.end(), buff.begin(), buff.end() );
}
Only keep in mind, that this may/will cause reallocation of the internal memory and several copies of the elements, but we're talking about char, so it's not a big deal.
You can avoid these reallocations using std::vector::reserve, if you have idea about the final size of bar.
I'd create a container class myself, use std::vector<char> internally, and create a wrapper slice class which holds a pointer to the container class and an index into the vector. The container class would hold the length foo. The container would have an iterator returning slices, each slice would have an iterator returning char.
[edit]
This solution also allocates contiguous memory.
After the question was reworded, you're probably looking for std::vector< std::array<char, 3> >
Memory will be contiguous for all elements. Assuming the last dimentsion is indeed a build time const.
Example:
std::vector< std::array<char, 3> > bar;
std::array<char, 3> foo = { 'a', 'b', 'c' };
bar.insert(bar.end(), 10, foo);
std::vector<char> bar(foo)
Constructs foo chars with in the vector, but because char is a built in type the constructor won't be called so it will be garbage values until initialised.
Instead use std::vector<char> bar(foo, char()) to fill it with initialised chars.

Pointer to a multidimensional vector

I am trying to initialize a pointer (*vectorName) with a 2D vector 366 by 4.
Both
vector<int> *vectorName = new vector<int>(366, new vector<int>(4));
and
vector<int> *vectorName = new vector<int>(366, vector<int>(4));
do not work and give me the error
Error: no instance of constructor "std::vector, <_Ty, _Alloc>::vector [with_ty=int, _Alloc=std_allocator]"
argument types are (const int, std::vector>*)
What can I do?
This is happening within the main function.
vector<int> *vectorName = new vector<int>(366, vector<int>(4));
The above doesn't work because the vector constructor template (ignoring a few things) looks as follows:
vector <TYPE> (SIZE, variable of type TYPE);
And in vector<int>(366, vector<int>(4)), vector <int> (4) is not of type int.
To create a vector with 366 elements that are vector of ints of size 4:
vector<vector<int> > *vectorName = new vector<vector<int> >(366, vector<int>(4));
or, if you don't need a pointer: (which you quite possibly don't)
vector<vector<int> > vectorName(366, vector<int>(4));
As a side note, if it's a fixed size 2D vector, why are you using vector, and not just an array. This would be much simpler:
int arr[366][4];
I assume that you're trying to use a pointer to a vector in order to get a dynamic C-array of vectors. There's no reason to do that. You can use a vector of vectors instead:
vector< vector<int> >
You can initialize that like this:
vector< vector<int> > vec(4);
for (size_t i = 0; i < 4; ++i) {
vec[i].resize(366);
}
Usage example:
vec[3][365] = 3;
If however you really do want a pointer to such a vector:
vector< vector<int> >* vec = new vector< vector<int> >(4);
for (size_t i = 0; i < 4; ++i) {
(*vec)[i].resize(366);
}
(*vec)[3][365] = 3;
If your size is constant and you're using a C++11 compiler, you can use an easier way, std::array:
array<array<int, 366>, 4> arr;
// Usage example
arr[3][365] = 3;
Or a pointer to a dynamically allocated one:
array<array<int, 366>, 4>* arr = new array<array<int, 366>, 4>;
// Usage example
(*arr)[3][365] = 3;
Are you trying to do this? This makes a 2D vector of vectors with int. It creates 366 vectors with a vector with size 4,where all items are initialized to zero. Now you have a 2D vector of 366 by 4.
vector<vector<int> > twod( 366, vector<int>(4,0));
and if you would like a pointer to this vector:
vector<vector<int> >* twodptr = &twod;
if you would really need this.

Can i push an array of int to a C++ vector?

Is there any problem with my code ?
std::vector<int[2]> weights;
int weight[2] = {1,2};
weights.push_back(weight);
It can't be compiled, please help to explain why:
no matching function for call to ‘std::vector<int [2], std::allocator<int [2]> >::push_back(int*&)’
The reason arrays cannot be used in STL containers is because it requires the type to be copy constructible and assignable (also move constructible in c++11). For example, you cannot do the following with arrays:
int a[10];
int b[10];
a = b; // Will not work!
Because arrays do not satisfy the requirements, they cannot be used. However, if you really need to use an array (which probably is not the case), you can add it as a member of a class like so:
struct A { int weight[2];};
std::vector<A> v;
However, it probably would be better if you used an std::vector or std::array.
You cant do that simply.
It's better you use either of these:
vector <vector<int>> (it's basically a two dimensional vector.It should work in your case)
vector< string > (string is an array of characters ,so you require a type cast later.It can be easily.).
you can declare an structure (say S) having array of int type within it i.e.
struct S{int a[num]} ,then declare vector of
vector< S>
So indirectly, you are pushing array into a vector.
Array can be added to container like this too.
int arr[] = {16,2,77,29};
std::vector<int> myvec (arr, arr + sizeof(arr) / sizeof(int) );
Hope this helps someone.
Arrays aren't copy constructable so you can't store them in containers (vector in this case). You can store a nested vector or in C++11 a std::array.
You should use std::array instead of simple array:
#include <vector>
#include <array>
std::vector<std::array<int, 2>> weights;
std::array<int, 2> weight = {1, 2};
weights.push_back(weight);
or with a constructor:
std::vector<std::array<int, 2>> weights;
weights.push_back(std::array<int, 2> ({1, 2});
One possible solution is:
std::vector<int*> weights;
int* weight = new int[2];
weight[0] =1; weight[1] =2;
weights.push_back(weight);
Just use
vector<int*> .That will definitely work.
A relevant discussion on the same topic : Pushing an array into a vector
Situation like:
int arr[3] = { 1, 2, 3 };
std::vector<int[]> v;
v.push_back(arr);
doesn't work with error "cannot initialize array in vector with .."
This, could be worked well
int * arr = new int[3] { 1, 2, 3 };
std::vector<int*> v;
v.push_back(arr);
To instantiate the vector, you need to supply a type, but int[2] is not a type, it's a declaration.

Multi-dimensional vector initialization

I have following std::vector declaration:
std::vector<std::vector<std::vector<int> > > m_input;
I am initializing it as follows:
m_input.resize (100);
m_output.resize(100);
for (int i = 0; i < 100; ++i) {
m_input [i].resize(100);
m_output[i].resize(100);
for (int j = 0; j < 100; ++j){
m_input [i][j].resize(100);
m_output[i][j].resize(100);
}
}
How can I achieve this via the member initializer list?
std::vector<T> has a constructor that takes two arguments, a number of elements and an initial value. In your case, you want to initialize m_input with 100 copies of a std::vector<std::vector<int> > , so it'd be : m_input(100, X). Now, that X in turn is a vector of 100 std::vector<int>, which in turn contains a hundred ints:
: m_input(100, std::vector<std::vector<int> >(100, std::vector<int>(100, 0)))
my_class::my_class()
: m_input(100, std::vector< std::vector<int> >(100, std::vector<int>(100) ))
{
}
That said, implementing a multi-dimensional field should be done by projecting into a one-dimensional one, as Viktor said in his comment to the question.
If you can assert that your vector dimensions are going to be of a fixed length, then why not use std::array?
For example:
std:array<std::array<std::array<int, 100>, 100>, 100>
That way you can take advantage of all the memory being contiguously allocated (as hinted at by Viktor_Sehr in the comments), without the added implementation woes of accessing a 1-dimensional array in a 3-dimensional way.