Bingo, Computer Graphics & Game Developer

矩阵"快速"初始化

我将我尝试的心路历程都记录在了这里。

这里的快速实质上是代表了代码书写的高效率。在重造数据结构里线性表的轮子的时候,遇到了需要构造NxM的矩阵需求,因为NxM可以动态构建出来,这没什么。

如下,可以非常方便的造一个简单的NxM的矩阵轮子出来

class t3Matrix
{
public:
    // 构造函数参数里给出行列即可
    t3Matrix(int row, int col):col(col), row(row)
    {
        m = new int*[row]();
        for(int i = 0; i < row; i++)
            m[i] = new int[col]();
    }

    ~t3Matrix()
    {
        for(int i = 0; i < row; i++)
            delete[] m[i];

        delete[] m;
    }

    int **m;
    int col, row;
};

问题来了,如何赋值,倘若是以往的2x2, 3x3事实上都是好解决的。

void t3Matrix2x2::create(int a00, int a01, int a10, int a11)
{
    // do something...
}

void t3Matrix3x3::create(int a00, int a01, int a02, int a10, int a11, int a12)
{
    // do something...
}

// etc... 

实际使用的时候这样的方法也不免为一个好决策。这里我颇受Eigen的影响, 他的矩阵初始化办法颇为简便易读,他是这样的。

void main()
{
    // NxM
    t3Matrix m(2, 3);

    // core!
    m << 1, 2,
         3, 4,
         5, 6;
}

这才像话,立马动手抄,但是Eigen过于庞大,也只能依样画葫芦尝试着去实现。

尝试1

移位运算符与stream联系非常迫切,兴许有效。这里我尝试着这样去试着使用istream,ostream配合着完成这样的初始化。

class t3Matrix
{
public:
    t3Matrix();
    ~t3Matrix();
};

ostream& operator<<(ostream& os, t3Matrix& m);

istream& operator>>(istream& is, t3Matrix& m);

思来想去,我最多能够做到使用cin,cout为矩阵初始化和输出,并不能在代码中实现初始化动作。

void fuck()
{
    t3Matrix m(n, m);
    // 标准输入初始化矩阵
    cin >> m;
    // 抛却m.print()方式标准输出
    cout << m;
}

然而这并没有什么卵用,期间我甚至尝试着让t3Matrix继承std::ostream。注意!OSX下XCode不会对以下代码报错

class A:public std::ostream
{
public:
    // 如若不为ostream构造,那么你将面临两次调用matrix析构函数的问题(Windows上VS编译无法通过)
    // 解决办法是写为ostream(NULL)提供一个streambuf参数即可,当然也可以给NULL 
    A(){}

    // 会被二次调用
    ~A(){}
};
class A:public std::ostream
{
public:
    // 运行正常
    A():std::ostream(NULL){}

    ~A(){}
};


尝试2

这回另辟蹊径,想起了重载逗号运算符。重载这个运算符实在是太少见了,以至于我和同学说起时,惊讶的反应:这**玩意也要重载?

其实需求很明显只要m << 1, 2, 3, 4;能够一路正确的读取即可,<<的优先级高于,,加上从左到右的运算顺序。

所以只要满足m << 1的返回值能够与重载,的运算符左参数相符,那么其实就是t3Matrix自身了。

以下写法已证实可行

class t3Matrix
{
public:
    // ...
    t3Matrix& operator,(int value)
    {
        // 赋该value到正确的位置
        // do something...
        return *this;
    }

    t3Matrix& operator<<(int value)
    {
        // 赋该value到正确的位置
        // do something...
        return *this;
    }
};

void main()
{
    t3Matrix m(2, 3);
    m << 1, 2,
         3, 4,
         5, 6;
}

其实难度不在于”<<”的重载,而是想到”,”的重载才是

已更新至t3DataStructures