我试图创建一个动态分配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)
...
答案 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];
这也可以让你检查索引的边界。