模板c ++分配动态矩阵2D

时间:2016-05-16 17:40:14

标签: c++ templates matrix 2d

我试图创建一个动态分配2D矩阵的模板。 通常我所做的是:

float **Allocate_matrix_float (int m, int n)
{
 float **v;  
 int   i;    
 if (m < 1 || n < 1) {
     printf ("** Invalid parameter **\n");
     return (NULL);
     }

  v = (float **) calloc (m, sizeof(float *));
  if (v == NULL) {
     printf ("** Unsufficient memory  **");
     return (NULL);
     }

  for ( i = 0; i < m; i++ ) {
      v[i] = (float*) calloc (n, sizeof(float));
      if (v[i] == NULL) {
         printf ("**  Unsufficient memory  **");
         return (NULL);
         }
      }
  return (v); 
}


float **free_matrix_float (int m, int n, float **v)
{
  int  i;  
  if (v == NULL) return (NULL);
  if (m < 1 || n < 1) { 
     printf ("** invalid parameter**\n");
     return (v);
     }
  for (i=0; i<m; i++) free (v[i]); 
  free (v);     
  return (NULL); 
}

但是,我想创建一个模板来分配任何类型的2D矩阵。任何人都可以帮助我吗? 理想的是:

template<typename T> 
T**Allocate_matrix(int n, int m)
...

2 个答案:

答案 0 :(得分:0)

您的所有分配和解除分配代码都可以替换为

std::vector<std::vector<float>> matrix(m, std::vector(n));

严重。它甚至在超出范围时解除分配,因此几乎没有内存管理问题。

#include <iostream>
#include <vector>

int main()
{
    size_t m;
    size_t n;

    std::cin >> m >> n;

    // floats initialized to 0.0
    std::vector<std::vector<float>> fltmatrix(m, std::vector<float>(n));
    // doubles initialized to 0.0
    std::vector<std::vector<double>> dblmatrix(m, std::vector<double>(n));
    // bools initialized to true
    std::vector<std::vector<bool>> boolmatrix(m, std::vector<bool>(n), true);
    // ints initialized to 42
    std::vector<std::vector<int>> intmatrix(m, std::vector<int>(n, 42));
} <-- all vectors are released here.

几乎不需要任何努力。

但是,因为每个向量都是它自己的独立实体,并且你有m + 1个向量,所以你的程序需要在内存中有m + 1个不同的位置才能返回一个值。这可能会对您的程序性能产生非常糟糕的影响,因为小型矩阵(例如3x3)无法充分利用CPU的缓存,这在处理大量矩阵时非常非常明显。如果您不在乎,请停止阅读并使用矢量方法的简单向量。

如果你关心,请在一个类中包装一维矢量:

#include <iostream>
#include <vector>

template<class TYPE>
class Matrix
{
private:
    size_t rows, columns;
    std::vector<TYPE> matrix;
public:
    Matrix(size_t numrows, size_t numcols) :
            rows(numrows), columns(numcols), matrix(rows * columns)
    {
    }

    Matrix(size_t numrows, size_t numcols, TYPE init) :
            rows(numrows), columns(numcols), matrix(rows * columns, init)
    {
    }

    TYPE & operator()(size_t row, size_t column)
    {
        // check bounds here
        return matrix[row * columns + column];
    }

    TYPE operator()(size_t row, size_t column) const
    {
        // check bounds here
        return matrix[row * columns + column];
    }

    size_t getRows() const
    {
        return rows;
    }
    size_t getColumns() const
    {
        return columns;
    }
    friend std::ostream & operator<<(std::ostream & out, const Matrix & in)
    {
        for (int i = 0; i < in.getRows(); i++)
        {
            for (int j = 0; j < in.getColumns(); j++)
            {
                out << in(i, j) << ' ';
            }
            out << std::endl;
        }

        return out;
    }
};

int main()
{
    size_t m;
    size_t n;

    std::cin >> m >> n;

    // floats initialized to 0.0
    Matrix<float> fltmatrix(m, n);
    std::cout << fltmatrix << std::endl;
    // doubles initialized to 0.0
    Matrix<double> dblmatrix(m, n);
    std::cout << dblmatrix << std::endl;
    // bools initialized to true
    Matrix<bool>  boolmatrix(m, n, true);
    std::cout << boolmatrix << std::endl;
    // ints initialized to 42
    Matrix<int> intmatrix(m, n, 42);
    std::cout << intmatrix << std::endl;
}

付出更多努力,但应该更快。查看您的计划,看看Matrix是否适合您。

包含

operator<<作为输出便利性,并作为如何访问Matrix单元格的示例。

如果你只是拥有来使用数组......事情会变得更加丑陋。首先,你必须得到Rule of Three (and possibly Rule of Five) compliant并获得一些额外的功能,坦率地说,你可能不会在前几次做对。

我甚至不确定如果我只是敲出一个就能说得对,而且我有一个非常好的选择,所以我不会去。你可以获得的是一个矩阵,它不会花时间在使用前初始化矩阵。如果这是一个问题(个人资料,个人资料,个人资料!),我会称之为一个新问题。当前的问题使用calloc,因此看起来不像OP。

答案 1 :(得分:0)

由于paddy使用向量向量提及here不实用,难以更改并且遇到缓存未命中。除了使用裸指针在C ++方面是不切实际的,它提供了更好的工具,如运算符重载。 以paddy的实现为基础,您的2d矩阵可以通过以下方式实现:

template <class T>
class SimpleMatrix
{
public:
    SimpleMatrix( int rows, int cols, const T& initVal = T() )
        : m_data( rows * cols, initVal )
        , m_rows( rows )
        , m_cols( cols )
    {    
    }

    // Direct vector access and indexing
    operator const vector<T>& () const        { return m_data; }
    int Index( int row, int col ) const       { return row * m_cols + col; }

    // Get a single value
          T & Value( int row, int col )       { return m_data[Index(row,col)]; }
    const T & Value( int row, int col ) const { return m_data[Index(row,col)]; }

    // Proxy structure to allow [][] indexing
    struct Proxy
    {
    private:
        friend class SimpleMatrix<T>;
        SimpleMatrix<T>* m_matrix;
        int m_row;
        Proxy( SimpleMatrix<T>* m, int row ) : m_matrix(m), m_row(row) {}
    public:
              T & operator[] ( int col )       { return m_matrix->Value(m_row, col); }
        const T & operator[] ( int col ) const { return m_matrix->Value(m_row, col); }
    };

          Proxy operator[]( int row )        { return Proxy(this, row); }
    const Proxy operator[]( int row ) const  { return Proxy(const_cast<SimpleMatrix<T>*>(this), row); }

private:
    vector<T> m_data;
    int m_rows;
    int m_cols;
};

并按以下方式使用它:

SimpleMatrix<int> m(10, 2);
const SimpleMatrix<int>& cm = m;
m[1][1] = 1;
cout << cm[1][1];

这也可以让你检查索引的边界。