C++以内存安全的方式使用给定向量的大小创建2D阵列



如何实现以下目标:

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

首先,我知道我可以用new来做这件事,但我必须记住以后要删除它,如果可能的话,我宁愿不必处理内存的释放。

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

第三,我不能(或者可能不知道如何)使用std::array,因为显然"局部变量不能用作非类型参数"。(我是从VS2013编译对话中复制粘贴的,对这一点几乎没有理解)。

第四,我正在考虑使用unique_ptr。问题是,我知道如何将unique_ptr用于1D阵列,如std::unique_ptr<int> arr{ new int[N] },但不知道如何将其用于2D阵列。

最后,我知道我总是可以围绕总是在堆上创建的C样式数组编写自己的瘦包装器,或者编写自己的2D数组类。但是,在C++(C++11)中,是否有本地或标准的库方法可以做到这一点?

std::experimental::array_view是在压缩缓冲区上具有动态大小边界的n维数组的视图。

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

通过视图对象进行访问,它将具有您期望从数组中进行的操作。存储与查看存储的方式是分开管理的。

为1维和2维的情况编写这个array_view的简化版本并不棘手。但结果是您的代码具有高性能,并且在使用时非常清晰。(array_view的)粘合代码可能有点棘手,但一旦测试,它应该是可靠的:类似的构造很可能很快就会添加到std中,这意味着它不会长期保持模糊。

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

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

我建议你为它写一个类。

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

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::vector< std::vector<int> > vec2d (vec.size(), vec);

其将使用来自CCD_ 22的值来初始化每一行。如果你不想这样做,那么就不要再进行最后的争论了。

通过1D阵列模拟2D阵列怎么样?就像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(不确定性能是否足够好)。

最新更新