Initializing a Two Dimensional Std::Vector

Initializing a two dimensional std::vector

Use the std::vector::vector(count, value) constructor that accepts an initial size and a default value:

std::vector<std::vector<int> > fog(
ROW_COUNT,
std::vector<int>(COLUMN_COUNT)); // Defaults to zero initial value

If a value other than zero, say 4 for example, was required to be the default then:

std::vector<std::vector<int> > fog(
ROW_COUNT,
std::vector<int>(COLUMN_COUNT, 4));

I should also mention uniform initialization was introduced in C++11, which permits the initialization of vector, and other containers, using {}:

std::vector<std::vector<int> > fog { { 1, 1, 1 },
{ 2, 2, 2 } };

initializing a two dimensional vector from a 2 dimensional array in C++

You could use for_each if you just want to avoid writing a loop and let the algorithm do it for you: https://godbolt.org/z/jxT8vfhPr

#include <algorithm>
#include <iostream>
#include <vector>

int main()
{
int a[4][4] = {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12},
{13,14,15,16}
};
std::vector<std::vector<int>> b;

std::for_each(a, a + 4, [&b](auto v){
b.push_back(std::vector<int>(v, v + 4));
});

std::for_each(cbegin(b), cend(b), [&b](auto v) {
std::copy(cbegin(v), cend(v), std::ostream_iterator<int>(std::cout, " "));
std::cout << "\n";
});
}

initializing 2d vector using only 1 line c++

Try this:

std::vector<std::vector<int>> twoDimVector(3, std::vector<int>(2, 0));

how to initialize a 2D vector C++

You have to resize the outer vector before the first for loop.

The inner vector can be resized and then assigned to, or items pushed back to it.

Matrix::Matrix(unsigned int nb_row, unsigned int nb_col) 
{
int i, j;
m_nbRow = nb_row;
m_nbCol = nb_col;

m_data.resize(m_nbCol);
for(i = 0; i < m_nbCol; i ++)
{
for(j = 0; j <m_nbRow; j ++)
{
m_data[i].push_back(<some value>);
}
}
}

or

Matrix::Matrix(unsigned int nb_row, unsigned int nb_col) 
{
int i, j;
m_nbRow = nb_row;
m_nbCol = nb_col;

m_data.resize(m_nbCol);
for(i = 0; i < m_nbCol; i ++)
{
m_data[i].resize(m_nbRow);
for(j = 0; j <m_nbRow; j ++)
{
m_data[i][j] = <some value>;
}
}
}

If you want to initialize the elements of the matrix to zero, you can simplify it to:

Matrix::Matrix(unsigned int nb_row, unsigned int nb_col) 
{
m_nbRow = nb_row;
m_nbCol = nb_col;
m_data.resize(m_nbCol, std::vector<long>(m_nbRow));
}

PS

Normally, the first index of matrix corresponds to a row while the second index corresponds to a column. You are using them the other way around in your post. I assume you have a reason for that.

How does C++ create different vectors in two dimensional vector initialization?

From the constructor reference

3) Constructs the container with count copies of elements with value value.

There are no references to tmp, just copies. All the individual vectors are distinct, and modifying one won't modify any of the others.

List initialisation of two dimensional std::array

In this declaration

std::array<std::array<int,2>,2> x = {{0,1},{2,3}};

you have three nested aggregates. The first pair of values enclosed in braces

{0,1}

is considered by the compiler as an initializer of the second aggregate that is present in the declaration as one sub-aggregate. So the second pair of values in braces

{2,3}

are considered by the compiler as redundant that has no corresponding object.

You could declare the array for example like

std::array<std::array<int, 2>, 2> x = { { {0,1},{2,3} } };

The braces may be elided when an aggregate is initialized. (C++17 Standard, 11.6.1 Aggregates)

12 Braces can be elided in an initializer-list as follows. If the
initializer-list begins with a left brace, then the succeeding
comma-separated list of initializer-clauses initializes the elements
of a subaggregate; it is erroneous for there to be more
initializer-clauses than elements. If, however, the initializer-list
for a subaggregate does not begin with a left brace, then only enough
initializer-clauses from the list are taken to initialize the elements
of the subaggregate; any remaining initializer-clauses are left to
initialize the next element of the aggregate of which the current
subaggregate is an element.

So in this declaration

std::array<std::array<int,2>,2> x = {0,1,2,3};

the braces are elided and the aggregate is initialized as it is described in the quote..

In this declaration

std::vector<std::vector<int>> y = {{0,1},{2,3}};

there is used the constructor of the class std::vector that accepts std::initializer_list as an argument. In this case the constructor builds as many elements of the vector as there are elements in the initializer list.

Initializing multi-dimensional std::vector without knowing dimensions in advance

Using push_back() should be fine, as long as the vector has reserved the appropriate capacity.

If your only hesitancy to using push_back() is the copy overhead when a reallocation is performed, there is a straightforward way to resolve that issue. You use the reserve() method to inform the vector how many elements the vector will eventually have. So long as
reserve() is called before the vector is used, there will just be a single allocation for the needed amount. Then, push_back() will not incur any reallocations as the vector is being filled.

From the example in your cited source:

std::vector<std::vector<int>> matrix;
matrix.reserve(M);
for (int i = 0; i < M; i++)
{
// construct a vector of ints with the given default value
std::vector<int> v;
v.reserve(N);
for (int j = 0; j < N; j++) {
v.push_back(default_value);
}

// push back above one-dimensional vector
matrix.push_back(v);
}

This particular example is contrived. As @kei2e noted in a comment, the inner v variable could be initialized once on the outside of the loop, and then reused for each row.

However, as noted by @Jarod42 in a comment, the whole thing can actually be accomplished with the appropriate construction of matrix:

std::vector<std::vector<int>> matrix(M, std::vector<int>(N, default_value));

If this initialization task was populating matrix with values from some external source, then the other suggestion by @Jarod42 could be used, to move the element into place to avoid a copy.

std::vector<std::vector<int>> matrix;
matrix.reserve(M);
for (int i = 0; i < M; i++)
{
std::vector<int> v;
v.reserve(N);
for (int j = 0; j < N; j++) {
v.push_back(source_of_value());
}

matrix.push_back(std::move(v));
}

How to initialize all elements of a two-dimensional array to a particular value?

You can use std::fill:

for(auto &arr : two_dim)
std::fill(std::begin(arr), std::end(arr), value);

This will work for many arrays and containers, like std::vector, std::array, and C arrays.

Also note that you can use memset to initialize all elements of an array to values other than -1 and 0. It's just that all the bytes in each element will have the same value, like 0x12121212.

Initializing values to two dimensional vectors during declaration

You can't have both a constructor call and a list initialization, stick to one, e.g.:

vector<vector<int>> plain{{23,43,45,56},
{67,85,13,59},
{48,23,9,57},
{24,52,90,12}};

(You can omit the = for list initialization.)

On your edit: Well, the error explains it all, reading it would help. You need C++11 mode for list initialization. If you don't want that, you'll have to copy with the ctor to prepare the 2D array and then fill it in after construction.



Related Topics



Leave a reply



Submit