【问题标题】:Setting pointer to arbitrary dimension array?将指针设置为任意维度数组?
【发布时间】:2013-11-11 15:16:46
【问题描述】:

当我想初始化一个多维数组时,我通常只使用指针。例如,对于我使用的两个维度:

double **array

我使用三个:

double ***array

但是,我想根据指示维度的命令行参数设置多维数组。一旦你有一个具有你想要的维数的变量,有没有办法设置一个任意大小的数组?

【问题讨论】:

  • 您是否考虑过使用第三方库?对我来说,听起来你正在寻找一个矩阵类; Eigen 是个不错的选择。
  • 你可以试试用void*
  • 除非您特别需要任意行长度分配大小 矩阵中,否则在现代 C++ 程序中绝对没有理由这样做(甚至 并不是一个合理的理由,因为它具有相当多的工程远见)。
  • When I want to initiate a multidimensional array, I usually just use pointers.
  • @MichaelLeVine 最基本的方法是向量的向量。您的问题的其余部分(处理任意数量的维度)是一个设计问题:数组维度 mean 在应用程序的上下文中。任意数量的维度表示您正在尝试将含义更改为应用程序的 instance。这是可能的,但非常混乱,并且作为实际应用表明您没有正确考虑您的设计。

标签: c++ arrays multidimensional-array


【解决方案1】:

即使整个问题表明存在设计缺陷,您也可以(在某种程度上)完成此操作:

template<typename T>
class MultiArray
{
public:
    MultiArray(std::size_t dimen, std::size_t dimen_size) : _dimensions(dimen)
    {
        _data = new T[dimen * dimen_size];
    }

    // implment copy constructor, copy-assignment operator, destructor, and move constructors as well

    T* operator[](int i)
    {
        assert(0 <= i && i < _dimensions); // bounds check for your dimension
        return &_data[i];
    }
private:
    T* _data;
    std::size_t _dimensions;
};

int main()
{
    MultiArray<int> a(5, 2);
    a[4][1] = 3;
    std::cout << a[4][1] << std::endl;
    return 0;
}

如果您希望它呈锯齿状,则必须对每个“维度”的边界进行更多的数学计算和维护。

您遇到的问题是使尺寸对您的应用程序有意义。通常,多维数组表示某些东西(例如,2D 向量可以表示笛卡尔空间,3D 或 4D 向量可用于处理 3D 图形的数据)。在第 4 维之后,为数组找到有效含义变得模糊不清,并且随着每个新维度维护其背后的逻辑变得越来越复杂。

【讨论】:

  • 你有什么建议作为一种聪明的方法来设计一个结构来解决这个问题:我在一个函数中有 n 个术语,每个术语都有 m 个可能的形式。我需要计算 n 项与所有可能的 m 项的任何组合的所有值。
  • @MichaelLeVine 您刚才描述的是一个二维数组(一个维度用于您的表单,另一个用于每个表单上的元素)。它基本上是一个排列计算。
  • 否,但我还需要存储任意形式的术语组合的函数输出。我正在解决一个需要递归算法的组合问题,因此我需要能够查找以前的输出(因为查找它们比重新计算要快几倍)。
【解决方案2】:

您可能对以下允许您使用任何“动态”维度的代码感兴趣:

#include <cassert>
#include <cstddef>

#include <vector>

template<typename T>
class MultiArray
{
public:
    explicit MultiArray(const std::vector<size_t>& dimensions) :
        dimensions(dimensions),
        values(computeTotalSize(dimensions))
    {
        assert(!dimensions.empty());
        assert(!values.empty());
    }

    const T& get(const std::vector<size_t>& indexes) const
    {
        return values[computeIndex(indexes)];
    }
    T& get(const std::vector<size_t>& indexes)
    {
        return values[computeIndex(indexes)];
    }

    size_t computeIndex(const std::vector<size_t>& indexes) const
    {
        assert(indexes.size() == dimensions.size());

        size_t index = 0;
        size_t mul = 1;

        for (size_t i = 0; i != dimensions.size(); ++i) {
            assert(indexes[i] < dimensions[i]);
            index += indexes[i] * mul;
            mul *= dimensions[i];
        }
        assert(index < values.size());
        return index;
    }

    std::vector<size_t> computeIndexes(size_t index) const
    {
        assert(index < values.size());

        std::vector<size_t> res(dimensions.size());

        size_t mul = values.size();
        for (size_t i = dimensions.size(); i != 0; --i) {
            mul /= dimensions[i - 1];
            res[i - 1] = index / mul;
            assert(res[i - 1] < dimensions[i - 1]);
            index -= res[i - 1] * mul;
        }
        return res;
    }

private:
    size_t computeTotalSize(const std::vector<size_t>& dimensions) const
    {
        size_t totalSize = 1;

        for (auto i : dimensions) {
            totalSize *= i;
        }
        return totalSize;
    }

private:
    std::vector<size_t> dimensions;
    std::vector<T> values;
};

int main()
{
    MultiArray<int> m({3, 2, 4});

    m.get({0, 0, 3}) = 42;
    m.get({2, 1, 3}) = 42;

    for (size_t i = 0; i != 24; ++i) {
        assert(m.computeIndex(m.computeIndexes(i)) == i);
    }
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-12
    • 1970-01-01
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    • 2012-10-07
    相关资源
    最近更新 更多