可变长度多维数组

C++: Variable length multidimensional array

本文关键字:数组      更新时间:2023-10-16

我需要一个二维数组,其中两个维度的长度在编译时都是未知的。我想要[][]访问

关于这个已经有几个问题,建议boost::multi_array, std::vector<std::vector<type>>,为x维分配一个数组,为y维分配x数组,等等。

问题是我不控制数据,它已经作为单个连续数组存在(大小为x*y)。我有一个指向它的指针和两个维度的大小,我或多或少地包装它以获得[][]访问。

我想避免创建一大堆对象(比如分配一个std::vector数组并将它们全部指向正确的东西),并且boost.

我考虑创建一个类来保存维度和指针,并重载[][],但这不起作用,因为[][]是两个操作符,第二个[]应用于不同的对象。

最终,我正在寻找一些相当于使用[][]作为某种access(int x, int y)函数的语法糖的东西。这可能吗?

您可以将它包装在一个类中并重载operator [],例如:

template <typename T>
class MultiArray
{
public:
    explicit MultiArray(T* arr, int sizex, int sizey) : data(arr), sizey(sizey) {}
    const T* operator [] (int x) const { return &data[x * sizey]; }
    T* operator [] (int x) { return &data[x * sizey]; }
private:
    T* data;
    int sizey;
};

生活例子

需要有两个类DataTypeP和DataTypePP。在初始化DataTypeP时,需要将内存块分配给不同的DataTypeP引用。

class DataTypeP {
    int *ptr;
public:
    int operator[](int y){ return ptr[y];}
};
class DataTypePP{
    DataTypeP  *bPtr;
public:
    DataTypeP  operator[](int x){ return bPtr[x];}
};
int main(){
    DataTypePP a;
    cout<<a[1][2];
    return 0;
}

使用std::vector<std::vector<type*>>,您可以使用自定义输入操作符构建内部向量,该操作符遍历数据并返回指向每个数据的指针。

例如:

size_t w, h;
int* myData = retrieveData(&w, &h);
std::vector<std::vector<int*>> data;
data.reserve(w);
template<typename T>
struct myIterator : public std::iterator<std::input_iterator_tag, T*>
{
    myIterator(T* data) :
      _data(data)
    {}
    T* _data;
    bool operator==(const myIterator& rhs){return rhs.data == data;}
    bool operator!=(const myIterator& rhs){return rhs.data != data;}
    T* operator*(){return data;}
    T* operator->(){return data;}
    myIterator& operator++(){data = &data[1]; return *this; }
};
for (size_t i = 0; i < w; ++i)
{
    data.emplace_back(myIterator<int>(&myData[i * h]),
        myIterator<int>(&myData[(i + 1) * h]));
}

生活例子

此解决方案的优点是为您提供了一个真正的STL容器,因此您可以使用特殊的for循环、STL算法等。

for (const auto& i : data)
  for (const auto& j : i)
    std::cout << *j << std::endl;
std::cout << "or with index access: " << std::endl;
for (size_t i = 0; i < w; ++i)
  for (size_t j = 0; j < h; ++j)
    std::cout << *data[i][j] << std::endl;

但是,它确实创建了指针的向量,所以如果你使用像这样的小数据结构,你可以直接复制数组中的内容。