我有以下代码来分配3d数组:
int ***allocate3DArray(int y, int x, int r) {
int ***array = (int ***) malloc(sizeof(int **) * y);
for (int i = 0; i < y; i++) {
array[i] = (int **) malloc(sizeof(int *) * x);
for (int j = 0; j < x; j++) {
array[i][j] = (int *) malloc(sizeof(int) * r);
for (int k = 0; k < r; k++) {
array[i][j][k] = 0;
}
}
}
return array;
}
void free3d(int ***arr, int y, int x, int r) {
for (int i = 0; i < y; i++) {
for (int j = 0; j < x; j++) {
free(arr[i][j]);
}
free(arr[i]);
}
free(arr);
}
这似乎有些笨拙,如果我的malloc失败,则很难进行错误处理。
也就是说,这非常符合人体工程学,因为我可以像这样简单地访问一个元素:int a = arr[x][y][z]
初始化具有相同人体工程学灵活性并同时减轻上述缺点的3d数组的最佳方法是什么?
我尝试过:
std::array < std::array < std::array < int, radius >, image.cols >, image.rows > houghSpace;
但我遇到了错误:
error: non-type template argument is not a constant expression
std::array < std::array < std::array < int, radius >, image.cols >, image.rows > houghSpace;
^~~~~~
sobel.cpp:117:49: note: initializer of 'radius' is not a constant expression
sobel.cpp:116:15: note: declared here
const int radius = image.rows / 2;
^
sobel.cpp:117:71: error: expected a type
std::array < std::array < std::array < int, radius >, image.cols >, image.rows > houghSpace;
^
sobel.cpp:117:86: error: C++ requires a type specifier for all declarations
std::array < std::array < std::array < int, radius >, image.cols >, image.rows > houghSpace;
^
答案 0 :(得分:2)
您想要一个具有长方体形状的3维数组。您当前拥有的是一个锯齿状的数组。每个通道可以有独立的大小,并且可以单独分配。这会产生3(4)个问题:
出于相同的原因,使用向量的解决方案也很糟糕。它只能解决一个问题-手动分配和解除分配。否则会变得更糟,因为它会存储更多的冗余数据。
您想要的是抽象一个连续的内存范围,以便可以将其解释为3d数组。
#include <iostream>
#include <memory>
#include <cstdint>
template <typename T>
struct Array3
{
Array3(size_t w, size_t h, size_t d) :
m_data(std::make_unique<T[]>(w*h*d)),
m_width(w),
m_height(h),
m_depth(d)
{
}
T& operator()(size_t x, size_t y, size_t z)
{
return m_data[(x * m_height + y) * m_depth + z];
}
const T& operator()(size_t x, size_t y, size_t z) const
{
return m_data[(x * m_height + y) * m_depth + z];
}
size_t width() const
{
return m_width;
}
size_t height() const
{
return m_height;
}
size_t depth() const
{
return m_depth;
}
T* data()
{
return m_data.get();
}
const T* data() const
{
return m_data.get();
}
private:
std::unique_ptr<T[]> m_data;
std::size_t m_width;
std::size_t m_height;
std::size_t m_depth;
};
int main()
{
Array3<int> a(10, 20, 30);
a(5, 10, 15) = 123;
std::cout << a(5, 10, 15);
}
使用操作符()而不是[]进行访问。可以使用[]完成,但需要更多样板代码和代理对象。
答案 1 :(得分:0)
一些有关C ++中数组的强烈建议
std::unique_ptr
或std::shared_ptr
。因此,切勿使用上述功能(allocate3DArray,free3d)
好的。因此,现在我们要切换到std::array
,您想知道错误消息。如您的示例所示,它们非常清晰。 std::array
的大小为静态。它不是动态的。因此,您需要提供一个编译时间常数来定义大小。
您要寻找的是std::vector
。它是动态的,可以增加大小,还具有索引运算符。
它可以不受限制地与索引运算符[]
一起使用。
请参见以下示例
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
// Dimensions for the 3 dimensional vector
size_t xSize{3};
size_t ySize{4};
size_t zSize{5};
int initialValue{0};
// Define 3 dimensional vector and initialize it.
std::vector<std::vector<std::vector<int>>> array3d(xSize, std::vector<std::vector<int>>(ySize, std::vector<int>(zSize,initialValue)));
array3d[1][2][3] = 42;
std::cout << "Result: " << array3d[1][2][3] << "\n";
return 0;
}