C ++以内存安全的方式使用给定向量的大小创建二维数组

C++ creating a 2D array using the size of a given vector, in a memory-safe manner

如何实现以下目标:

std::vector<int> vec = { 1, 2, 3 };
const int N = vec.size();
// Now create NxN 2D array.

首先,我知道我可以使用 new 来完成它,但我必须记住稍后将其删除,并且如果可能的话我宁愿不必处理内存的重新分配。

其次,我不能在堆栈上声明二维数组,因为 N 不是(在这种情况下也不可能)常量表达式。 (无论如何,我使用的是 VS2013,它不支持 constexpr。)

第三,我不能(或者可能不知道如何)使用 std::array 因为显然 "a local variable cannot be used as a non-type argument"。 (我是从VS2013的编译对话中复制粘贴过来的,对这一点了解不多)

第四,我正在考虑使用unique_ptr。问题是,我知道如何对一维数组使用 unique_ptr,例如 std::unique_ptr<int> arr{ new int[N] },但不知道如何对二维数组使用它。

最后,我知道我总是可以围绕始终在堆上创建的 C 样式数组编写自己的精简包装器,或者编写自己的二维数组 class。但是在 C++ (C++11) 中是否有一种本机或标准库的方式来执行此操作?

我建议你为它写一个class。

以下示例:set() 在设置值之前调整它的大小。运算符 [] returns 该行的列向量,因此当您应用运算符 [] 时,它 returns 所需的值。如果您发现任何问题,请告诉我 ;)。

class 2DVector {
 std::vector<std::vector<int>> m_items;

 void set(int value, size_t row, size_t column) {
   for (int i=m_items.size(); i<=row; i++) {
      m_items.push_back(std::vector<int>());
   }
   for (int i=0; i<m_items.size(); i++) {
      for (int j=m_items[i].size(); j<=column; j++) {
      m_items[i].push_back(0);
   }
   m_items[row][column] = value;
 }

 std::vector<int> &operator [](size_t index) {
   return m_items[index];
 }
}

用法:

2DVector v;
v.set(200, 0, 0);
v.set(201, 1, 0);
std::cout << v[0][0]; //prints 200
std::cout << v[1][0]; //prints 201

std::experimental::array_view 是一个 n 维数组的视图,在打包缓冲区上具有动态大小限制。

因此,一种方法是创建一个连续的缓冲区(例如 std::vector<T>std::unique_ptr<T[]>,然后将 array_view<T,2> 环绕在其周围。

通过视图对象访问,它将具有您应该从数组中获得的操作。存储与查看存储的方式分开管理。

为一维和二维情况编写此 array_view 的简化版本并不难。但结果是您的代码是高性能的,并且在使用时非常清晰。胶水代码(针对 array_view)可能有点棘手,但一旦经过测试,它应该是可靠的:并且类似结构将很快被添加到 std 的可能性意味着它不会一直晦涩难懂长.

根据我的经验,一旦我有了一个可靠的 array_view 类型,我就用它来代替我之前(低效地)使用 std::vector 传递数据包的地方过去。

如果你想自己写,我会跳过关于边界和索引的部分,只实现切片 -- [] 在第二个维度上 array_view returns a第一维 array_view,和 [] 第一维 array_view returns a T&.

用一维数组模拟二维数组怎么样?就像openCV2所做的那样

伪代码

class 2DVector {         
 void set(int value, size_t row, size_t column) {
   m_items[row * column_size + column];
 }

 int &operator [](size_t row, size_t column) {
   return m_items[row * column_size + column];
 }

 private:
   std::vector<int> m_items;
}

或者只使用 boost::multi_array(不确定性能是否适合您的情况)。

标准库的做法是:

std::vector< std::vector<int> > vec2d (vec.size(), vec);

这将使用 vec 中的值初始化每一行。如果你不想这样做,那么就不要再最后一个参数了。