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
中的值初始化每一行。如果你不想这样做,那么就不要再最后一个参数了。
如何实现以下目标:
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
中的值初始化每一行。如果你不想这样做,那么就不要再最后一个参数了。