多次元配列を開始したいときは、通常はポインターのみを使用します。たとえば、私が使用する 2 つの次元の場合:
double **array
そして3つのために私は使用します:
double ***array
ただし、次元を示すコマンドライン引数に基づいて多次元配列を設定したいと思います。必要な次元数の変数を取得したら、任意のサイズの配列を設定する方法はありますか?
多次元配列を開始したいときは、通常はポインターのみを使用します。たとえば、私が使用する 2 つの次元の場合:
double **array
そして3つのために私は使用します:
double ***array
ただし、次元を示すコマンドライン引数に基づいて多次元配列を設定したいと思います。必要な次元数の変数を取得したら、任意のサイズの配列を設定する方法はありますか?
この質問全体は設計上の欠陥を示していますが、これを (ある程度) 達成できます。
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 次元を超えると、配列の有効な意味を見つけることが難しくなり、その背後にあるロジックを維持することは、新しい次元ごとにますます複雑になります。
「動的」ディメンションを使用できるようにする次のコードに興味があるかもしれません。
#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;
}