如何将矢量<矢量<int>>转换为数组C++

How to convert vector<vector<int>> to array C++

本文关键字:lt gt 转换 C++ 数组 int 矢量      更新时间:2023-10-16

我想知道是否有一种更聪明的方法来将std::vector<std::vector<int>转换为数组,给定每个向量项的大小是固定的:

我正在使用:

  unsigned int cell_size = pCells[0].size();
  std::vector<int> kCells(pCells.size()*cell_size);
  for (unsigned int i=0; i<pCells.size(); i++){
     for (unsigned int j=0; j< cell_size; j++){
    kCells[i*cell_size+j] = pCells[i][j];
     }
  }
  // array
  int* lCells = &kCells[0];

从2d向量中获得int*的一种方便方法是使用临时向量来构建缓冲区,然后指向该缓冲区。这种方法的缺点是,您必须确保指针的寿命不会超过vector,并且vector不会以导致指针无效的方式被修改(通常情况下,这是任何可能导致元素重新分配或移动的情况)。如果你不介意,你可以使用

std::vector<std::vector<int>> data; // we assume this is populated
std::vector<int> builder;
builder.reserve(data.size() * data[0].size()); // reserve space in builder. not needed but useful if you already now how many elements you need
for (const auto& row : data)
    builder.insert(builder.end(), row.begin(), row.end()
int * non_owning_ptr = &builder[0];

现在您有一个指向生成器内容的非拥有指针,以及随之而来的所有陷阱。只要non_owning_ptr不离开声明builder的作用域,除了可能由于修改向量而导致的无效之外,陷阱是可以避免的。您可以将它传递给同一作用域中的函数,但不能向上传递到当前作用域之外。

另一个选择是使用std::unique_ptr<int[]>,但你需要确切地知道你需要多少元素,因为你不能增长unique_ptr。这比使用原始指针和new要好,因为您不需要记住在完成后调用delete。您仍然有相同的作用域问题,需要确保指针的寿命不会超过std::unique_ptr。你还必须确保你没有对它做任何操作,将删除指针,如调用reset。使用unique_ptr,您可以使用

std::vector<std::vector<int>> data; // we assume this is populated
auto builder = std::make_unique<int[]>(data.size() * data[0].size());
int * end = builder.get(); // for std::copy
for(const auto& row : data)
{
    std::copy(row.begin(), row.end(), end);
    end += row.size();
}
int * non_owning_ptr = builder.get();

获得数组的唯一另一种方法是将指针new向上,将数据复制到新的缓冲区中,然后在完成后delete。这仍然不是最大的,因为你必须记住调用delete,当你用缓冲区完成,但至少指针"拥有"的数据,可以传递到任何地方。你还必须确保无论你调用什么都不会在指针上调用delete,否则当你要删除指针时就会出现双delete。

std::vector<std::vector<int>> data; // we assume this is populated
int * buffer = new int[data.size() * data[0].size()];
int * end = buffer; // for std::copy
for(const auto& row : data)
{
    std::copy(row.begin(), row.end(), end);
    end += row.size();
}
// use buffer here
// don't forget this when done
delete [] buffer;

c++提供了许多比你正在做的更好的选择,从最好到最差列出:

  1. 构建您的vector<vector<int>>作为vector<int>,在必要时进行2D索引到1D数组,然后甚至不需要进行转换,直接使用vector<int>
  2. 使用#define s设置数组的大小、高度和宽度,使用array而不是vector来存储元素
  3. 最糟糕的情况是你所做的,更残酷的是你所做的:int* lCells = &kCells[0]意味着lCells是无效的,任何改变都会使kCells的迭代器无效

1需要在问题中的代码之外进行更改,因此我不会演示。2可以这样做,给定:#define WIDTH 3, #define HEIGHT 2,并且您的输入定义为:array<WIDTH, array<HEIGHT, int>> pCells,您可以这样做:

int lCells[WIDTH * HEIGHT];
for_each(begin(lCells), end(lCells), [i = cbegin(pCells), j = cbegin(pCells)->cbegin()](auto& it) mutable {
    if(j == i->cend()) j = (++i)->cbegin();
    it = *j++;
});
<<p> 生活例子/kbd>