【问题标题】:Why would I obtain weird output when overloading operator + and = for array pointer [duplicate]为什么在为数组指针重载运算符+和=时会得到奇怪的输出[重复]
【发布时间】:2021-06-05 08:24:49
【问题描述】:

提前非常感谢!我在使用 C++ 时编写自己的矩阵类,我使用一维数组来存储数据,并使用指向该数组的指针来管理我的数据。当我试图重载 operator= 时,会发生奇怪的事情......在 operator= 函数中打印的矩阵输出正确的东西,但它在函数之外输出奇怪的东西,我想不出任何理由来解释这个问题,下面是我的代码:

class Matrix2d{

    public:

        float* data;
        int rows;
        int cols;

        Matrix2d(int _rows, int _cols, float num){
            rows = _rows; cols = _cols;
            data = new float [rows * cols];
            std::fill(data, data + (rows * cols), num);
            return;
        }

        ~Matrix2d(){
            delete[] data;
        }

        Matrix2d operator+(const Matrix2d& matrix){
            if (matrix.cols != this->cols || matrix.rows != this->rows){
                std::cout << "[ERROR] Matrix size does not match." << std::endl;
                throw;
            }
            Matrix2d output(this->cols, this->rows, 0);
            float* ptr = output.data;
            for (int i = 0; i < this->rows * this->cols; ++i){
                *ptr = this->data[i] + matrix.data[i];
                ++ptr;
            }
            return output;
        }

        void operator=(const Matrix2d& matrix){
            this->rows = matrix.rows; this->cols = matrix.cols;
            delete[] this->data;
            this->data = matrix.data;
            std::cout << "Output from =" << std::endl;
            std::cout << *this << std::endl;
        }


        friend std::ostream& operator<<(std::ostream& stream, const Matrix2d& matrix){
            
            stream << "Matrix2d([";
            float* ptr = matrix.data;
            for (int i = 0; i < matrix.rows; ++i){
                stream << ((i == 0)? "[":"          [");
                for (int j = 0; j < matrix.cols; ++j){
                    stream << ptr << ((j == matrix.cols - 1)? "]":",");
                    ++ptr;
                }
                if (i != matrix.rows - 1){ stream << '\n'; }
            }
            stream << "])" << std::endl;
            return stream;
        }
};

我在 operator= 函数内打印了矩阵,它是正确的,但它不在该函数之外:

int main(){
    
    Matrix2d A(3, 3, 1), B(3, 3, 5);
    cout << A << endl;
    cout << B << endl;
    A = A+B;
    cout << A << endl;
    return 0;

}

输出:

Matrix2d([[1,1,1]
          [1,1,1]
          [1,1,1]])

Matrix2d([[5,5,5]
          [5,5,5]
          [5,5,5]])

Output from =
Matrix2d([[6,6,6]
          [6,6,6]
          [6,6,6]])

Matrix2d([[9.93522e-38,0,6]
          [6,6,6]
          [6,6,6]])

我不知道前两个条目是从哪里来的,后两个矩阵的内存地址完全一样,我不明白为什么只有两个值发生了变化,地址:

Matrix2d([[0x159fb30,0x159fb34,0x159fb38]
          [0x159fb3c,0x159fb40,0x159fb44]
          [0x159fb48,0x159fb4c,0x159fb50]])

Matrix2d([[0x159fac0,0x159fac4,0x159fac8]
          [0x159facc,0x159fad0,0x159fad4]
          [0x159fad8,0x159fadc,0x159fae0]])

Output from =
Matrix2d([[0x159bb20,0x159bb24,0x159bb28]
          [0x159bb2c,0x159bb30,0x159bb34]
          [0x159bb38,0x159bb3c,0x159bb40]])

Matrix2d([[0x159bb20,0x159bb24,0x159bb28]
          [0x159bb2c,0x159bb30,0x159bb34]
          [0x159bb38,0x159bb3c,0x159bb40]])

如何在我退出函数后简单地更改相同地址的值?另外,如果我使用类似的东西:

C=A+B; A=C;

这将给出正确的结果。

【问题讨论】:

    标签: c++ arrays pointers


    【解决方案1】:

    在您的operator= 中,您分配了this-&gt;data = matrix.data。当临时实例被销毁时,matrix.data 被释放,您现在正在引用释放的内存。

    但是,对于 C=A+B,有一种特殊情况称为 copy elision,其中生成的实例是在 C 创建的,实际上没有调用 operator=

    由于您使用const Matrix2d&amp; 定义了运算符,因此它是一个复制分配器。重新分配另一个块并复制数据应该是正确的。

    或者,创建一个移动分配器(接受 Matrix2d&amp;&amp; 的单个参数)并在移动后将 matrix.data 设置为 nullptr。

    【讨论】:

    • 非常感谢您的耐心等待!但是为什么只有两个值发生了变化,而不是全部被释放了内存。
    • @ZongyueLu 当由于缺少用户定义的复制构造函数和错误的赋值运算符而导致代码完全损坏时,问为什么没有意义。您需要先修复这些问题,然后尝试实现operator +
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多