【问题标题】:Trying to reload an operator in c++, but it doesn't seem to work尝试在 C++ 中重新加载运算符,但它似乎不起作用
【发布时间】:2018-12-07 00:26:07
【问题描述】:

问题:我用相同的解决方案重载了运算符**=,尽管使用运算符*= 似乎并没有改变矩阵的内容,也许我错误地声明了运算符重载方法。

同时操作符*工作正常,实际上是乘以矩阵,我事先查过了。

输出:

3 4 -5 
8 0 7 
8 9 -4 

8 7 7 
-6 0 6 
2 2 9 

3 4 -5 
8 0 7 
8 9 -4 

这是代码本身:

struct WrappedMatrix{
        int n;
        int ** Matrix;
    };

    struct WrappedVector{
        int n;
        int * Vector;
    };

    WrappedVector linearizedMatrix(WrappedMatrix matrix){
        WrappedVector vector;
        vector.n = matrix.n * matrix.n;
        vector.Vector = new int[vector.n];
        for(int i = 0; i < matrix.n; i++){
            for(int j = 0; j < matrix.n; j++){
                 int k = j + (int) (i*sqrt(vector.n));
                 vector.Vector[k] = matrix.Matrix[i][j];
            }
        }
        return vector;
    }

    WrappedMatrix normalMatrix(WrappedVector vector){
        WrappedMatrix matrix;
        matrix.n = sqrt(vector.n);
        matrix.Matrix = new int * [matrix.n];
        for(int i = 0; i < matrix.n; i++){
            matrix.Matrix[i] = new int[matrix.n];
            for(int j = 0; j < matrix.n; j++){
                int k = j + (int) (i*sqrt(vector.n));
                matrix.Matrix[i][j] = vector.Vector[k];
            }
        }
        return matrix;
    }

    WrappedVector operator*(const WrappedVector& vector1, const WrappedVector& vector2) {
        if(vector1.n != vector2.n) {
            cout << "Матриці різних розмірів!" << endl;
            return vector1;
        }
        WrappedMatrix matrix1 = normalMatrix(vector1);
        WrappedMatrix matrix2 = normalMatrix(vector2);
        WrappedMatrix result;
        result.n = matrix1.n;
        result.Matrix = new int * [result.n];
        for(int i = 0; i < result.n; i++){
            result.Matrix[i] = new int[result.n];
        }
        for(int i = 0; i < result.n; i++){
            for(int j = 0; j < result.n; j++){
                for(int k = 0; k < result.n; k++){
                    int p1 = matrix1.Matrix[i][k];
                    int p2 = matrix2.Matrix[k][j];
                    result.Matrix[i][j] += p1 * p2;
                }
            }
        }
        WrappedVector resultV = linearizedMatrix(result);
        return resultV;
    }

    //?
    WrappedVector operator*=(const WrappedVector& vector1, const WrappedVector& vector2) {
        if(vector1.n != vector2.n) {
            cout << "Матриці різних розмірів!" << endl;
            return vector1;
        }
        WrappedMatrix matrix1 = normalMatrix(vector1);
        WrappedMatrix matrix2 = normalMatrix(vector2);
        WrappedMatrix result;
        result.n = matrix1.n;
        result.Matrix = new int * [result.n];
        for(int i = 0; i < result.n; i++){
            result.Matrix[i] = new int[result.n];
        }
        for(int i = 0; i < result.n; i++){
            for(int j = 0; j < result.n; j++){
                for(int k = 0; k < result.n; k++){
                    int p1 = matrix1.Matrix[i][k];
                    int p2 = matrix2.Matrix[k][j];
                    result.Matrix[i][j] += p1 * p2;
                }
            }
        }
        WrappedVector resultV = linearizedMatrix(result);
        return resultV;
    }


    int main() {

        WrappedMatrix matrix;
        matrix.n = 3;
        matrix.Matrix = new int * [matrix.n];
        matrix.Matrix[0] = new int[matrix.n];
        matrix.Matrix[1] = new int[matrix.n];
        matrix.Matrix[2] = new int[matrix.n];
        matrix.Matrix[0][0] = 3;
         matrix.Matrix[0][1] = 4;
         matrix.Matrix[0][2] = -5;
        matrix.Matrix[1][0] = 8;
         matrix.Matrix[1][1] = 0;
         matrix.Matrix[1][2] = 7;
         matrix.Matrix[2][0] = 8;
         matrix.Matrix[2][1] = 9;
         matrix.Matrix[2][2] = -4;
        WrappedVector vector = linearizedMatrix(matrix);

        cout << vector << endl;

        WrappedMatrix matrix1;
        matrix1.n = 3;
        matrix1.Matrix = new int * [matrix1.n];
        matrix1.Matrix[0] = new int[matrix1.n];
        matrix1.Matrix[1] = new int[matrix1.n];
        matrix1.Matrix[2] = new int[matrix1.n];
        matrix1.Matrix[0][0] = 8;
        matrix1.Matrix[0][1] = 7;
        matrix1.Matrix[0][2] = 7;
        matrix1.Matrix[1][0] = -6;
        matrix1.Matrix[1][1] = 0;
        matrix1.Matrix[1][2] = 6;
        matrix1.Matrix[2][0] = 2;
        matrix1.Matrix[2][1] = 2;
        matrix1.Matrix[2][2] = 9;
        WrappedVector vector1 = linearizedMatrix(matrix1);

        cout << vector1 << endl;

        vector *= vector1;

        cout << vector;


        return 0;
    }

提前谢谢你!

【问题讨论】:

  • 您按值返回 WrappedMatrix。按值返回任何内容都需要该值具有正确的复制语义。您的WrappedMatrix 没有正确的复制语义,因为它违反了Rule of 3。要么实现您在链接中看到的那些缺失的功能,要么使用std::vector&lt;int&gt;std::vector&lt;std::vector&lt;int&gt;&gt; 而不是int *int ** 来省去麻烦。
  • 同样,WrappedVector 也是如此。对你来说最简单的事情就是使用我提到的vector。这可以解决所有指针问题(但可能存在其他问题)。
  • 注意:存储数组的数组可能会成为性能杀手。对于小型矩阵,通常会发现程序花费更多时间来追踪指针和加载缓存而不是处理数字。考虑使用单个 1 维数组或向量,并使用 row * number_columns + column 自己执行 2D 1D 映射。 Example with std::vector
  • 问自己一个简单的问题:既然您将const 引用传递给您的*= 重载,那么您希望如何修改您传递的const 对象?你不能(这里的例外情况不相关)。 *= 并没有按照您认为的方式工作。
  • @SamVarshavchik 实际上,更改int ** Matrix 指向的数据是可能的(只有外部指针不能在没有 const-casting 的情况下修改)。

标签: c++ matrix operator-overloading


【解决方案1】:

从技术上讲,这不是一个答案,到目前为止,我只是修改了代码,如果有时间,我会在今晚晚些时候添加。我今天早上刚刚整理了一些东西,想你不妨看看,这样它就不会无所事事了:

#include <iostream>
#include <vector>
#include <cstdarg>

class matrix{
    public:
        matrix(){};
        matrix(std::initializer_list<std::vector<int>> vectors):x(vectors){}
        ~matrix(){};

        const int& size(){ return this->x.size(); } //# of vectors
        //ALT: ex. print: 3x3, 4x5, 7x3
        //void size(){ std::cout<<"Dim: "<<this->x.size<<"x"<<this->x.front().size()<<std::endl;
        void add(const std::vector<int>& arr){ this->x.push_back(arr); }
        const std::vector<std::vector<int>>& extract(){ return this->x; } //Returns entire matrix
        const std::vector<int>& getVector(const int& row){ return this->x.at(row); } //Returns specific vector from matrix

        matrix operator*(const matrix& m){ //More params
            //Stuff here
        }
        matrix operator*=(const matrix& m){ //More params
            //Stuff here
        }

    private:
        std::vector<std::vector<int>> x;
};

//Can break the center out to make one for vectors too
std::ostream& operator<<(std::ostream& os, matrix& m){
    for (auto& it:m.extract()){
        for (auto& jt:it){
            os<<jt<<" ";
        }
        os<<std::endl;
    }
    os<<std::endl;
    return os;
}


int main(){
    matrix m({{2,5,8,11,14},
              {3,6,9,12,15},
              {4,7,10,13,16}});
    std::cout<<m;

    return 0;
}

据我所知,这就是 cmets 的内容。在我看来,使用起来要容易得多,尽管如果您被要求以某种特定方式创建结构和访问向量,它可能不是您所需要的。

另外,我没有弄清楚你的数学结果是什么,所以我没有在运算符中添加任何东西,我可能会在稍后添加一些叉积或点积示例,如果那是你正在做的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-28
    • 2012-01-10
    • 1970-01-01
    • 2016-05-31
    • 1970-01-01
    • 1970-01-01
    • 2013-11-01
    相关资源
    最近更新 更多