Dynamic memory allocation for a 3d array that uses minimal memory and in contiguous form in C ++?

I want to build a 3D matrix nx * ny * nz in which nx, ny, nz is about 200, so I need to use dynamic allocation, and since I have a lot of these matrices, I need to build these matrices so that it uses minimal memory as far as possible, how can I do this and how can I build in related form?

+1
source share
3 answers

You can write a wrapper around std::vectorand overload operator()to access the elements of the matrix. Elements are saved adjacent to 1D std::vector, and operator()converts 3D indexes to 1D index in std::vector. If the matrix were 2D, it would look like this: from 2D to 1D:

| 1 2 3 |
| 4 5 6 |  ---> [1 2 3 4 5 6 7 8 9] 
| 7 8 9 |

This ordering is called the main line .

Here is an example of a class that overloads operator()to convert three-dimensional indexes to the 1D row index:

#include <iostream>
#include <vector>

template <class T>
class Matrix3D
{
public:
    Matrix3D(size_t m, size_t n, size_t o)
    : m_(m), n_(n), o_(o), data_(m*n*o) {}

    T& operator()(size_t i, size_t j, size_t k)
    {
        return data_[(i * n_ * o_) + (j * o_) + k];
    }

    const T& operator()(size_t i, size_t j, size_t k) const
    {
        return data_[(i * n_ * o_) + (j * o_) + k];
    }

private:
    std::vector<T> data_;
    size_t m_, n_, o_;
};

int main()
{
    Matrix3D<float> m(4, 3, 2);
    m(0,0,0) = 12.3f;
    m(3,2,1) = 45.6f;
    std::cout << m(0,0,0) << " " << m(3,2,1) << "\n";
}

The Boost.MultiArray library does the same thing as this (and much more), but can be used for any N. dimension.

+1
source

Using C ++ 11:

template<typename T,size_t M,size_t N,size_t O>
using Matrix3D = std::array<std::array<std::array<T,O>,N>,M>;

std::unique_ptr<Matrix3D<double,200,200,200>> mat(new Matrix3D<double,200,200,200>);

(*mat)[m][n][o] = 10.0;

If you write a function make_unique, the variable declaration will be:

auto mat = std::make_unique<Matrix3D<double,200,200,200>>();

So, the whole program might look like this:

#include <memory> // std::unique_ptr for convenient and exception safe dynamic-memory management
#include <array>  // std::array because it behaves much better than raw arrays 

template<typename T,size_t M,size_t N,size_t O>
using Matrix3D = std::array<std::array<std::array<T,O>,N>,M>;

// A simple `make_unique`
template<typename T,typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

int main() {
    auto mat = make_unique<Matrix3D<double,200,27,200>>();
    (*mat)[199][26][199] = 10.0; // store 10.0 in the last element
}

, ++ 11, , . , , , ( using Matrix3D =) - clang 3.0. GCC . Variadic ( make_unique) GCC, Clang, MSVC VS11.

, * ++ 11:

#include <memory>
#include <array>

template<typename T,size_t M,size_t N,size_t O>
struct Matrix3D {
    std::array<std::array<std::array<T,O>,N>,M> array;
};

// A simple `make_unique` that supports only zero-argument construction.
template<typename T>
std::unique_ptr<T> make_unique() {
    return std::unique_ptr<T>(new T);
}

int main() {
    auto mat = make_unique<Matrix3D<double,200,27,200>>();
    mat->array[199][26][199] = 10.0; // store 10.0 in the last element
}

* GCC MSVC.

+2

, new, , , , ( ):

struct array3d {
    double array[200][200][200];
};

std::auto_ptr<areay3d> array(new array3d);

, .

, double . , , : subscript 2d- .. std::valarray<double> , .

+1

All Articles