2010-01-16 78 views
14

在C,如果我想创建一个矩阵结构,我会用:C++矩阵

struct matrix { 
    int col, row; 
    double data[1]; // I want the matrix entries stored 
        // right after this struct 
} 

然后,我可以用

matrix* allocate_matrix(int row, int col) { 
    matrix* m = malloc(sizeof(matrix) + sizeof(double) * (row * col - 1)); 
    m->row = row; m->col = col; 
    return m; 
} 

分配它现在做我做的当量在C++ ?

编辑:

我想知道实现C++矩阵类cannonical方式。

+1

你应该填写'...'来清除一些答案中的混淆。 – GManNickG 2010-01-16 08:07:51

+0

好通话;这足够吗? – anon 2010-01-16 08:19:08

回答

-2

在C++中,你可以使用这样的:

matrix *p = new matrix; 

之后,

delete p; 
+0

OP在问题的原始语句中并不明确,但意图显然是'struct'的最后一个成员,它是一个变量/不确定大小的数组,因此只需使用'new'而不是'malloc'即可没有工作。 – jamesdlin 2010-01-16 08:26:06

12

C++主要是C的超集,你可以继续做你在做什么。

也就是说,在C++中,你应该做的是定义一个适当的Matrix类来管理它自己的内存。例如,它可以由内部的std::vector提供支持,并且您可以覆盖operator[]operator()以从C++ FAQ中适当地将索引编入索引(例如,请参阅:How do I create a subscript operator for a Matrix class?)。

为了让你开始:

class Matrix 
{ 
public: 
    Matrix(size_t rows, size_t cols); 
    double& operator()(size_t i, size_t j); 
    double operator()(size_t i, size_t j) const; 

private: 
    size_t mRows; 
    size_t mCols; 
    std::vector<double> mData; 
}; 

Matrix::Matrix(size_t rows, size_t cols) 
: mRows(rows), 
    mCols(cols), 
    mData(rows * cols) 
{ 
} 

double& Matrix::operator()(size_t i, size_t j) 
{ 
    return mData[i * mCols + j]; 
} 

double Matrix::operator()(size_t i, size_t j) const 
{ 
    return mData[i * mCols + j]; 
} 

(请注意,上面并没有做任何边界检查的,我把它作为一个练习模板,以便它适用于比double其他的东西。 )

3

可能这样做。唯一的区别是你需要从malloc投下结果。

相反,您可以使用vector作为具有计算索引的一维数组或嵌入向量。 (前者匹配你的代码更好。)

例如:

template <typename T> // often, they are templates 
struct matrix 
{ 
    // should probably be hidden away, and the class would 
    // provide `at` and `operator()` for access 
    int col, row; 
    std::vector<T> data; 

    matrix(int columns, int rows) : 
    col(columns), row(rows), 
    data(col * row) 
    {} 

} 

matrix m(4, 4); 
m.data[1 + 1 * 4] = /* ... */; 

或者:

template <typename T> 
struct matrix 
{ 
    int col, row; 
    std::vector<std::vector<T> > data; 

    matrix(int columns, int rows) : 
    col(columns), row(rows), 
    data(col, std::vector(row)) 
    {} 
} 

matrix m(4, 4); 
m.data[1][1] = /* ... */; 

但这些仅是例子。你想成为一个完整的班级;如果你想要更多的建议,编辑你的问题,并澄清你想知道实现矩阵类的规范方式。

有预先存在的矩阵类。我最喜欢的是从提升,UBLAS

+0

你的意思是'data [1] [1]',而不是'data [1,1]'。 (从技术上讲,'m.data [1] [1]'。) – jamesdlin 2010-01-16 08:23:12

+0

哎呀,完全清除了那个。 – GManNickG 2010-01-16 08:36:07

+0

我不认为vector的vector会成为一个非常有效的实现。 – bobobobo 2010-08-02 18:54:22

4

建立一个高效和高质量的矩阵类有很多微妙之处,幸运的是有几个好的实现浮出水面。

想想你是想要一个固定大小的矩阵类还是可变大小的矩阵类。 即你可以这样做:

// These tend to be fast and allocated on the stack. 
matrix<3,3> M; 

或者你需要能够做到这一点

// These are slower but more flexible and partially allocated on the heap 
matrix M(3,3); 

有支持两种风格很好的图书馆,以及一些支持。 他们有不同的分配模式和不同的表现。

如果您想自己编写代码,那么模板版本需要一些模板知识(duh)。如果在紧密循环中使用,那么动态的需要一些黑客来解决大量的小分配问题。

1

你可以用模板做,如果矩阵大小在编译时已知:

template <int width, int height> 
class Matrix{ 
    double data[height][width]; 
    //...member functions 
}; 
30

诺塔好处。

此答案现在有20个upvotes,但它不是,不打算作为std::valarray的代言。

根据我的经验,安装和学习使用全面的数学库(如Eigen)花费的时间会更多。 Valarray的功能比竞争对手少,但效率并不高,或者特别容易使用。

如果你只需要一点线性代数,并且你已经死定了反对向你的工具链添加任何东西,那么可能valarray将适合。但是,被卡住无法表达数学上正确的解决方案是一个非常糟糕的位置。数学是无情的,无情的。使用正确的工具来完成这项工作。


标准库提供std::valarray<double>。这里有一些其他人提出的std::vector<>,意图作为对象的通用容器。 valarray,鲜为人知的,因为它是更特化的(不使用“专门”作为C++术语),具有几个优点:

  • 它不分配额外的空间。当分配时,A vector将达到最接近的2的幂,所以您可以调整它的大小而不必每次重新分配。 (您仍然可以调整valarray的大小;它仍然与realloc()一样昂贵。)
  • 您可以将其切片以轻松访问行和列。
  • 算术运算符按照您的预期工作。

当然,使用C的优势在于您无需管理内存。维度可以位于堆栈中,也可以位于切片对象中。

std::valarray<double> matrix(row * col); // no more, no less, than a matrix 
matrix[ std::slice(2, col, row) ] = pi; // set third column to pi 
matrix[ std::slice(3*row, row, 1) ] = e; // set fourth row to e 
+2

+1将我指向stl – Shep 2012-04-14 08:36:50

+0

@Shep不得不承认我从来没有真正使用过'valarray' ......我尝试了几次,切片类是一种痛苦。这可能值得一看,并且比其他答案在这里提出的建议更好,但是有更好的库。 (好吧,至少看起来是这样,我还没有真正使用过,Boost BLAS应该不错。) – Potatoswatter 2012-04-14 10:19:01

+2

Yikes,这是朝着10个upvotes前进的。 'std :: valarray'很难使用,只支持基本的成员代数,并且它不是很流行。试试[Eigen Library](http://eigen.tuxfamily.org/),它非常易于使用,功能强大且颇受欢迎。 – Potatoswatter 2013-01-07 03:58:06

2

你可以使用一个模板:

#include <iostream> 
using std::cerr; 
using std::endl; 

//qt4type 
typedef unsigned int quint32; 

template <typename T> 
void deletep(T &) {} 
template <typename T> 
void deletep(T* & ptr) { 
    delete ptr; 
    ptr = 0; 
} 
template<typename T> 
class Matrix { 
    public: 
     typedef T value_type; 
     Matrix() : _cols(0), _rows(0), _data(new T[0]), auto_delete(true) {}; 
     Matrix(quint32 rows, quint32 cols, bool auto_del = true); 

     bool exists(quint32 row, quint32 col) const; 
     T & operator()(quint32 row, quint32 col); 
     T operator()(quint32 row, quint32 col) const; 
     virtual ~Matrix(); 

     int size() const { return _rows * _cols; } 
     int rows() const { return _rows; } 
     int cols() const { return _cols; } 
    private: 
     Matrix(const Matrix &); 
     quint32 _rows, _cols; 
     mutable T * _data; 
     const bool auto_delete; 
}; 
template<typename T> 
Matrix<T>::Matrix(quint32 rows, quint32 cols, bool auto_del) : _rows(rows), _cols(cols), auto_delete(auto_del) { 
    _data = new T[rows * cols]; 
} 
template<typename T> 
inline T & Matrix<T>::operator()(quint32 row, quint32 col) { 
    return _data[_cols * row + col]; 
} 
template<typename T> 
inline T Matrix<T>::operator()(quint32 row, quint32 col) const { 
    return _data[_cols * row + col]; 
} 

template<typename T> 
bool Matrix<T>::exists(quint32 row, quint32 col) const { 
    return (row < _rows && col < _cols); 
} 

template<typename T> 
Matrix<T>::~Matrix() { 
    if(auto_delete){ 
     for(int i = 0, c = size(); i < c; ++i){ 
      //will do nothing if T isn't a pointer 
      deletep(_data[i]); 
     } 
    } 
    delete [] _data; 
} 

int main() { 
    Matrix<int> m(10,10); 
    quint32 i = 0; 
    for(int x = 0; x < 10; ++x) { 
     for(int y = 0; y < 10; ++y, ++i) { 
      m(x, y) = i; 
     } 
    } 
    for(int x = 0; x < 10; ++x) { 
     for(int y = 0; y < 10; ++y) { 
      cerr << "@(" << x << ", " << y << ") : " << m(x,y) << endl; 
     } 
    } 
} 

*编辑,固定一个错字。

2

对于矩阵类,您希望远离过载运算符[]
C++ FAQ 13.10

此外,在网络上搜索一些免费软件矩阵类。最坏的情况下,他们可以给你指导。最好的情况下,你必须编写更少的软件和调试

3

发布几年之后,C++ 11授予了我们一些新的可能性。

这里是一个的包括在我做饭了,应该给其他人谁在这个跌倒的现代化起点的OpenGL库的早期草案:

(注 - 这还有待检验或审核)

/*(KILLGPL: Incompatible with Libraries Linked to the GPL) 
============================================================================ 

"Free software" should be just that - free. Extreme copy-left licenses 
such as the GPL, GPL2, GPL3, etc, and their users have twisted the 
term "free" to meet their own anti-business, anti-closed source agendas by 
forcing licensees to relicense their software under the same "viral" terms 
and by forcing licensees to distribute sources with binary distributions. 
This license stands in protest of such licenses in an attempt to protect 
the freedoms that extreme copy-left licenses have been taking away from 
software developers for far too long. 

Permission is hereby granted, free of charge, to any person obtaining 
a copy of this software and associated documentation files (the 
"Software"), to deal in the Software with only one restriction: no part of 
it may be included in software projects that are distributed under "viral" 
licensing schemes like those found in the GPL, GPL2, GPL3, etc. 

There are no further usage restrictions. Licensees are encouraged to use 
this software in both open and closed source applications, so long as no 
part of the combined work is licensed under extreme copy-left licenses. 

The above copyright notice and this permission notice shall be included 
in all copies or substantial portions of the Software. Note - this notice 
does not have to appear in YOUR code, but must remain intact in the parts 
licensed under the KILLGPL. 

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/ 

#ifndef MATRIX_HPP 
#define MATRIX_HPP 

#include <array> 
#include <cstdint> 
#include <iterator> 
#include <initializer_list> 
#include <iosfwd> 

/// Forward Declarations Required for free-function friends 
template<typename T, std::size_t X, std::size_t Y> 
class Matrix; 

/** 
* Performs a component-wise comparison between the two provided matrices 
* 
* @param lhs the first matrix to compare 
* 
* @param rhs the second matrix to compare 
* 
* @return true if the two matrices are equal, otherwise false 
* 
*/ 
template<typename T, std::size_t X, std::size_t Y> 
bool operator==(const Matrix<T, X, Y>& lhs, const Matrix<T, X, Y>& rhs) noexcept; 

/** 
* Performs a component-wise comparison between the two provided matrices 
* 
* @param lhs the first matrix to compare 
* 
* @param rhs the second matrix to compare 
* 
* @return true if the two matrices are not equal, otherwise false 
* 
*/ 
template<typename T, std::size_t X, std::size_t Y> 
bool operator!=(const Matrix<T, X, Y>& lhs, const Matrix<T, X, Y>& rhs) noexcept; 

/** 
* Inserts the provided Matrix into the provided output stream 
* 
* @param stream the stream to insert the provided Matrix into 
* 
* @param matrix the Matrix to insert into the provided stream 
* 
* @return the provided stream 
* 
*/ 
template<typename T, std::size_t X, std::size_t Y> 
std::ostream& operator<<(std::ostream& stream, const Matrix<T, X, Y>& matrix); 

/** 
* Extracts a Matrix from the provided input stream 
* 
* @param stream the stream to extract from 
* 
* @param matrix the Matrix to extract into 
* 
* @return the provided input stream 
* 
*/ 
template<typename T, std::size_t X, std::size_t Y> 
std::istream& operator>>(std::istream& stream, Matrix<T, X, Y>& matrix); 

/** 
* A modern general-purpose object-oriented matrix class without any legacy hacks from C 
* 
* Several common matrix types are also defined in the following format: 
* 
* Matrix {number of rows} x {number of columns} {type abbreviation} 
* 
* where the predefined type abbreviations are: 
* type  - abbreviation 
* -------------------------- 
* double - D 
* float  - F 
* int64_t - L 
* uint64_t - UL 
* int32_t - I 
* uint32_t - UI 
* int16_t - S 
* uint16_t - US 
* int8_t - C 
* uint8_t - UC 
* 
* example: Matrix3x3F - A tuple that holds 3x3 float elements 
* 
* User-defined matrix types are expected to follow the aforementioned format. 
* 
* @tparam T the type of data stored in this matrix 
* 
* @tparam Rows the number of rows in this matrix 
* 
* @tparam Columns the number of columns in this matrix 
*/ 
template<typename T, std::size_t Rows, std::size_t Columns> 
class Matrix 
{ 
    static_assert(Rows > 0, "The number of rows in a Matrix must be greater than zero"); 
    static_assert(Columns > 0, "The number of columns in a Matrix must be greater than zero"); 

    /// Privileged free-functions 
    friend std::ostream& operator<<<>(std::ostream&, const Matrix<T, Rows, Columns>&); 
    friend std::istream& operator>><>(std::istream&, const Matrix<T, Rows, Columns>&); 
    friend bool operator!=<>(const Matrix<T, Rows, Columns>&, const Matrix<T, Rows, Columns>&); 
    friend bool operator==<>(const Matrix<T, Rows, Columns>&, const Matrix<T, Rows, Columns>&); 

    /// The actual container that holds the elements of this Matrix 
    std::array<T, Rows * Columns> values; 

    public: 

    /// A convenience field that provides the total number of elements in this Matrix 
    static constexpr std::size_t Length = Rows * Columns; 

    /** 
    * Retrieves the identity-matrix 
    * 
    * @return the identity-matrix 
    * 
    */ 
    static constexpr Matrix IDENTITY() noexcept; 

    /** 
    * Retrieves the zero-matrix 
    * 
    * @return the zero-matrix 
    * 
    */ 
    static constexpr Matrix ZERO() noexcept; 

    /** 
    * Constructs a Matrix with each element initialized to zero 
    * 
    */ 
    constexpr Matrix() noexcept; 

    /** 
    * Constructs a Matrix whose elements are initialized to the provided array 
    * 
    * @param elements the array to initialize this Matrix with 
    * 
    */ 
    explicit constexpr Matrix(const std::array<T, Rows * Columns>& elements) noexcept; 

    /** 
    * Constructs a Matrix whose elements are initialized to the provided array 
    * 
    * @param elements the array to initialize this Matrix with 
    * 
    */ 
    explicit constexpr Matrix(std::array<T, Rows * Columns>&& elements) noexcept; 

    /** 
    * Constructs a Matrix whose elements are initialized with the provided values 
    * 
    * @param element the first value 
    * 
    * @param elements all subsequent values 
    * 
    * <pre>Matrix<int, 3, 3> matrix(1, 2, 3, 1, 2, 3, 1,2 ,3);</pre> 
    * 
    */ 
    template<typename ...E> 
    explicit constexpr Matrix(T element, E&&... elements) noexcept; 

    /** 
    * Retrieves a const reference to the element at the provided row and column 
    * 
    * @param row the row to access 
    * 
    * @param column the column to access 
    * 
    * @return the element at the provided row and column 
    * 
    */ 
    /*constexpr*/const T& operator()(std::size_t row, std::size_t column) const noexcept; 

    /** 
    * Retrieves a reference to the element at the provided row and column 
    * 
    * @param row the row to access 
    * 
    * @param column the column to access 
    * 
    * @return the element at the provided row and column 
    * 
    */ 
    /*constexpr*/T& operator()(std::size_t row, std::size_t column) noexcept; 

    // TODO: Global Free Functions for performing transformations 
}; 

namespace detail 
{ 
    // thanks be to Cubbi @ cplusplus.com for enlightenment 
    template<int ...> struct sequence 
    { 

    }; 

    template<int N, int ...S> struct sequence_generator : sequence_generator<N - 1, N - 1, S...> 
    { 

    }; 

    template<int ...S> struct sequence_generator < 0, S...> 
    { 
     using type = sequence<S...>; 
    }; 

    template<std::size_t X, std::size_t Y> 
    constexpr int get_element(std::size_t pos) 
    { 
     return pos % Y == pos/Y; 
    } 

    template <typename T, std::size_t Rows, std::size_t Columns, int ...S> 
    constexpr std::array<T, Rows * Columns> get_identity_array(sequence<S...>) 
    { 
     return std::array<T, Rows * Columns> {{ get_element<Rows, Columns>(S)... }}; 
    } 
} 

template<typename T, std::size_t Rows, std::size_t Columns> 
bool operator==(const Matrix<T, Rows, Columns>& lhs, const Matrix<T, Rows, Columns>& rhs) noexcept 
{ 
    for(int i = 0; i < Matrix<T, Rows, Columns>::Length; ++i) 
    { 
     if(lhs[i] == rhs[i]) 
     { 
      return true; 
     } 
    } 
    return false; 
} 

template<typename T, std::size_t Rows, std::size_t Columns> 
bool operator!=(const Matrix<T, Rows, Columns>& lhs, const Matrix<T, Rows, Columns>& rhs) noexcept 
{ 
    for(int i = 0; i < Matrix<T, Rows, Columns>::Length; ++i) 
    { 
     if(lhs[i] != rhs[i]) 
     { 
      return true; 
     } 
    } 
    return false; 
} 

template<typename T, std::size_t Rows, std::size_t Columns> 
Matrix<T, Rows, Columns> operator-(const Matrix<T, Rows, Columns>& source) noexcept 
{ 
    Matrix<T, Rows, Columns> rv(source); 
    for(int i = 0; i < Matrix<T, Rows, Columns>::Length; ++i) 
    { 
     rv[i] *= -1; 
    } 
    return rv; 
} 

template<typename T, std::size_t Rows, std::size_t Columns> 
constexpr Matrix<T, Rows, Columns> Matrix<T, Rows, Columns>::IDENTITY() noexcept 
{ 
    return Matrix{detail::get_identity_array<T, Rows, Columns>(typename detail::sequence_generator<Rows * Columns>::type())}; 
} 

template<typename T, std::size_t Rows, std::size_t Columns> 
constexpr Matrix<T, Rows, Columns> Matrix<T, Rows, Columns>::ZERO() noexcept 
{ 
    return Matrix{}; 
} 

template<typename T, std::size_t Rows, std::size_t Columns> 
constexpr Matrix<T, Rows, Columns>::Matrix() noexcept 
{ 

} 

template<typename T, std::size_t Rows, std::size_t Columns> 
constexpr Matrix<T, Rows, Columns>::Matrix(const std::array<T, Rows * Columns>& values) noexcept : values(values) 
{ 

} 

template<typename T, std::size_t Rows, std::size_t Columns> 
constexpr Matrix<T, Rows, Columns>::Matrix(std::array<T, Rows * Columns>&& array) noexcept : values(array) 
{ 

} 

template<typename T, std::size_t Rows, std::size_t Columns> 
template<typename ...E> 
constexpr Matrix<T, Rows, Columns>::Matrix(T first, E&&... elements) noexcept : values {{ first, std::forward<T>(static_cast<T>(elements))... }} 
{ 

} 

template<typename T, std::size_t Rows, std::size_t Columns> 
/*constexpr*/const T& Matrix<T, Rows, Columns>::operator()(std::size_t row, std::size_t column) const noexcept 
{ 
    dynamic_assert(row >= 0 && row < Rows, "access violation (row index " << row << " out of range [" << Rows << "])"); 
    dynamic_assert(column >= 0 && column < Columns, "access violation (column " << column << " out of range [" << Columns << "])"); 
    return values[column * Rows + row]; 
} 

template<typename T, std::size_t Rows, std::size_t Columns> 
/*constexpr*/T& Matrix<T, Rows, Columns>::operator()(std::size_t row, std::size_t column) noexcept 
{ 
    dynamic_assert(row >= 0 && row < Rows, "access violation (row index " << row << " out of range [" << Rows << "])"); 
    dynamic_assert(column >= 0 && column < Columns, "access violation (column " << column << " out of range [" << Columns << "])"); 
    return values[column * Rows + row]; 
} 


/// Built-in library matrix types 
typedef Matrix<uint8_t, 2, 2> Matrix2x2UC; 
typedef Matrix<uint8_t, 3, 3> Matrix3x3UC; 
typedef Matrix<uint8_t, 4, 4> Matrix4x4UC; 

typedef Matrix<int8_t, 2, 2> Matrix2x2C; 
typedef Matrix<int8_t, 3, 3> Matrix3x3C; 
typedef Matrix<int8_t, 4, 4> Matrix4x4C; 

typedef Matrix<uint16_t, 2, 2> Matrix2x2US; 
typedef Matrix<uint16_t, 3, 3> Matrix3x3US; 
typedef Matrix<uint16_t, 4, 4> Matrix4x4US; 

typedef Matrix<int16_t, 2, 2> Matrix2x2S; 
typedef Matrix<int16_t, 3, 3> Matrix3x3S; 
typedef Matrix<int16_t, 4, 4> Matrix4x4S; 

typedef Matrix<uint32_t, 2, 2> Matrix2x2UI; 
typedef Matrix<uint32_t, 3, 3> Matrix3x3UI; 
typedef Matrix<uint32_t, 4, 4> Matrix4x4UI; 

typedef Matrix<int32_t, 2, 2> Matrix2x2I; 
typedef Matrix<int32_t, 3, 3> Matrix3x3I; 
typedef Matrix<int32_t, 4, 4> Matrix4x4I; 

typedef Matrix<uint64_t, 2, 2> Matrix2x2UL; 
typedef Matrix<uint64_t, 3, 3> Matrix3x3UL; 
typedef Matrix<uint64_t, 4, 4> Matrix4x4UL; 

typedef Matrix<int64_t, 2, 2> Matrix2x2L; 
typedef Matrix<int64_t, 3, 3> Matrix3x3L; 
typedef Matrix<int64_t, 4, 4> Matrix4x4L; 

typedef Matrix<float, 2, 2> Matrix2x2F; 
typedef Matrix<float, 3, 3> Matrix3x3F; 
typedef Matrix<float, 4, 4> Matrix4x4F; 

typedef Matrix<double, 2, 2> Matrix2x2D; 
typedef Matrix<double, 3, 3> Matrix3x3D; 
typedef Matrix<double, 4, 4> Matrix4x4D; 
#endif 
+0

非常好的例子。 – Vincent 2014-10-03 22:36:16

0

Github Link

// 
// iBS_Matrix.h 
// 
// 
// Created by nash on 11/29/15. 
// Copyright 2015 iBean Software. 
// All rights reserved. 
// current copy on Github: 
// 
#ifndef iBS_Matrix_h 
#define iBS_Matrix_h 

const int Matrix_MAJOR_VERSION = 1; 
const int Matrix_MINOR_VERSION = 0; 

#include <iostream> 
#include <vector> 
namespace iBS 
{ 
struct Matrix 
{ 
    std::vector<std::vector<int> > a; 

    Matrix& operator =(Matrix& o) 
    { 
     a.resize(o.a.size()); 
     for(int i=0;i<a.size();i++) 
      a[i].resize(o.a[i].size()); 
     for(int i=0;i<a.size();i++) 
      for(int j=0;j<a[i].size();j++) 
      { 
       a[i][j] = o.a[i][j]; 
      } 
     return *this; 
    } 

    Matrix& operator +(Matrix& o) 
    { 
     for(int i=0;i<a.size();i++) 
      for(int j=0;j<a[i].size();j++) 
      { 
       a[i][j] = a[i][j] + o.a[i][j]; 
      } 
     return *this; 
    } 
    Matrix& operator -(Matrix& o) 
    { 
     for(int i=0;i<a.size();i++) 
      for(int j=0;j<a[i].size();j++) 
      { 
       a[i][j] = a[i][j] - o.a[i][j]; 
      } 
     return *this; 
    } 
    Matrix& operator *(Matrix& o) 
    { 
     if(a[0].size() != o.a.size()) return *this; 

     Matrix tm; 
     tm.a.resize(a.size()); 
     for(int i=0;i<tm.a.size();i++) 
      tm.a[i].resize(o.a[0].size()); 

     for(int i=0;i<tm.a.size();i++) 
      for(int j=0;j<tm.a[i].size();j++) 
      { 
       tm.a[i][j] = 0; 
       for (int c=0; c<a[i].size(); c++) 
       { 
        tm.a[i][j] += a[i][c] * o.a[c][j]; 
       } 

      } 
     *this = tm; 
     return *this; 
    } 
    Matrix& operator ^(int power) 
    { 
     Matrix tM2; 
     tM2 = *this; 

    // not <= below \/ because first time counts as 2 
     for(int i=1; i<power; ++i) 
      *this = (*this) * (tM2); 

     return *this; 
    } 

    void print() 
    { 
     for(int i=0;i<a.size();i++) 
     { 
      for(int j=0;j<a[i].size();j++) 
      { 
       std::cout << a[i][j] << ' '; 
      } 
      std::cout << std::endl; 
     } 
     std::cout << std::endl; 
    } 
}; 

}; // end of namespace iBS 

#endif // iBS_Matrix_h 
0

没有 “规范” 的方式做在C++中,STL不提供类,如“马特里矩阵X”。但是有一些第三方库可以。鼓励您使用它们或编写您自己的实现。