使用`std::copy()`和`std::back_inserter()`函数。

14

我有两个类A和B,它们都有一个像下面这样的成员:

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

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

我发现当我使用std::copy()A::grid复制到B::grid时,它会失败。 这是我所做的:

// 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));

但是如果我删除初始化部分,那么std::copy函数就能正常工作。初始化部分有什么问题吗?


1
你为什么不简单地写 grid = a.grid; 呢? - T.C.
@ T.C. ,我也尝试使用 operator=(),它能正常工作。我只是想知道为什么在使用 std::copy 时出错 :) - Josper
1个回答

24

让我用一个简单的例子来向您展示。

std::vector<int> v = {1, 2, 3};
std::vector<int> v1;
std::copy(v.begin(), v.end(), std::back_inserter(v1));
在这种情况下,v1将会是1,2,3,正如预期的那样。现在考虑这个:
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));

现在,back_inserter push_back,所以v1将为0、0、0、1、2、3。如果您已经在目标中分配了必要的大小,则使用 begin() 迭代器而不是 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是1、2、3,如预期所示。


谢谢你的回答,它真的让我感到困惑。我可以问另一个问题吗?当我将grid[i][j].reserve(a.grid[i][j].size());修改为grid[i][j].resize(a.grid[i][j].size());并使用back_inserter时,它也可以正常工作。reserve和resize有什么区别?我知道reserve只是保留缓冲区,而resize会初始化值。但为什么resize会正确地工作呢? - Josper
@Josper:我认为你对grid[i][j]所做的任何操作,无论是调整大小还是保留,都不会产生任何影响。重要的是你是否调整了grid本身的大小。 - Armen Tsirunyan
这些中哪一个更高效? - nog642
@nog642:使用back_inserter的方法可能会遭受多次重新分配的困扰。 - Armen Tsirunyan
@ArmenTsirunyan 如果事先使用reserve()方法并使用back_inserter方法进行调用,那么这是否与最初的size方法本质上相同?还是有一个理由优选其中之一? - nog642

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接