Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using `std::copy()` with `std::back_inserter()`

Tags:

c++

copy

std

c++11

I have two class A and B both have a member like below:

class A {
  ...
  std::vector<std::vector<std::vector<size_t>>> grid;
}

class B {
  ...
  std::vector<std::vector<std::vector<size_t>>> grid;
}

I found when I use std::copy() to copy from A::grid to B::grid, it will fail. Here is what I do:

// Here is in B's constructor.
// I initialize B::grid with the same size of A::grid
grid = vector<vector<vector<size_t>>>(GetSetting().grid_cols());
for (int i = 0; i < GetSetting().grid_cols(); i++) {
  grid[i] = vector<vector<size_t>>(GetSetting().grid_rows());
  for (int j = 0; j < GetSetting().grid_rows(); j++) {
    grid[i][j].reserve(a.grid[i][j].size());
  }
}

// Copy from A to B
std::copy(a.grid.begin(), a.grid.end(), std::back_inserter(grid));

But if I remove initialize part, then the std::copy will work fine. What's wrong for the initialize part?

like image 299
Josper Avatar asked Feb 02 '17 08:02

Josper


1 Answers

Let me show you with a simplified example.

std::vector<int> v = {1, 2, 3};
std::vector<int> v1;
std::copy(v.begin(), v.end(), std::back_inserter(v1));

In this scenario v1 will be 1, 2, 3, as expected. Now consider this:

std::vector<int> v = {1, 2, 3};
std::vector<int> v1(3); //v1 has initial size!!
std::copy(v.begin(), v.end(), std::back_inserter(v1));

Now v1 will be 0, 0, 0, 1, 2, 3, because back_inserter push_backs. If you have already allocated the necessary size in the destination, then use the begin() iterator and not the back_insert_iterator:

std::vector<int> v = {1, 2, 3};
std::vector<int> v1(3); //v1 has initial size!!
std::copy(v.begin(), v.end(), v1.begin()); //use begin here

v1 is 1, 2, 3, as expected.

like image 81
Armen Tsirunyan Avatar answered Nov 11 '22 07:11

Armen Tsirunyan