【问题标题】:invalid initialization of non-const reference of type 'Matrix&' from an rvalue of type 'Matrix'从“Matrix”类型的右值对“Matrix&”类型的非常量引用进行无效初始化
【发布时间】:2017-09-08 16:21:45
【问题描述】:

我只是没有看到我的错误。关于此错误消息有很多问题,或者答案不适用,或者我看不到它们适用。也许应该改进错误消息?

Matrix a = Matrix(3, 4);
// fill a with values
Matrix c = Matrix(4, 4);
// fill c with values
a *= c - c; //this is where the compile error occurs

当我将行更改为 a *= c 时,它可以工作。所以我想 *= 运算符没有什么问题。

这是 Matrix *= 运算符:

Matrix &Matrix::operator *=(Matrix &B)
{
    Matrix M(rows(), B.cols());
    for (int i = 0; i<rows(); i++)
    {
        for (int j=0; j<B.cols(); j++)
        {
            for (int k=0; k<cols(); k++)
            {
                M(i,j) = M(i,j) + (*this)(i,k) * B(k,j);
            }
        }
    }
    return M;
}

这是 - 运算符:

Matrix operator -(Matrix &A, Matrix &B)
{
    //TODO: Check if matrices have same dimensions, exception else
    Matrix M(A.rows(), A.cols());
    for(int i=0; i<A.rows(); i++)
    {
        for(int j=0; j<A.cols(); j++)
        {
            M(i,j) = A(i,j)-B(i,j);
        }
    }
    return M;
}

【问题讨论】:

  • 不是问题,但operator *= 不应该返回对本地Matrix 的引用。如果有什么可以返回*this
  • 你可能想读一读,看看如何正确地重载你的操作符:stackoverflow.com/questions/4421706/operator-overloading
  • operator*= 预计会修改this 的值,然后返回对*this 的引用。

标签: c++ c++11 matrix operator-overloading


【解决方案1】:

通过c - c 命令,您可以通过operator- 生成一个新矩阵并将其返回。接下来,operator*= 引用一个矩阵,这就是编译器抱怨的地方。这样做是为了防止您发现底层对象将在您想要使用它时过期。

尝试将Matrix&amp; 更改为Matrix const&amp;。这将延长对象的生命周期,直到函数结束。另外,从 const 正确性的角度来看,它也更合适。

此外,您应该从您的operator*= 返回*this,并更改包含的矩阵。 (感谢@CoryKramer 指点,急于回答错过了)。

所以你的操作符基本上应该是这样的(只是基本概念,根本没有优化):

Matrix &Matrix::operator *=(Matrix const& B)
{
    Matrix M(rows(), B.cols());

    for (int i = 0; i<rows(); i++)
    {
        for (int j=0; j<B.cols(); j++)
        {
            for (int k=0; k<cols(); k++)
            {
                M(i,j) += (*this)(i,k) * B(k,j);
            }
        }
    }

    //copy -- or better move -- the temporary matrix into *this
    operator=(std::move(M));
    return *this;
}

【讨论】:

  • M 是一个局部变量。您无法安全地返回对它的引用。
  • @CoryKramer:当然应该更改并返回*this
  • 谢谢。我以为我现在会理解错误,但是通过您的修复,错误仍然存​​在。
  • @Sadik:我也将operator- 参数设置为const-references,即operator-(Matrix const&amp; A, Matrix const&amp; B),但这不应该是问题。真的是同样的问题,同样的错误信息吗? (只是询问,因为代码明确执行原始错误消息所要求的 - 提供对Matrix const&amp; 的(const)引用......)。您的代码中是否涉及其他未修复且可能存在类似问题的运算符?
  • 是的,它是完全相同的错误消息,尽管它现在返回*this。其他运算符也有同样的问题,但编译器指向的是同一行。
【解决方案2】:

解决方案是从

更改操作员签名
Matrix operator -(Matrix &A, Matrix &B);

Matrix operator -(const Matrix &A, const Matrix &B)

适用于所有运营商。我还必须添加一个新的运算符const double &amp; operator ()(int row, int column) const;,否则语句B(k,j) 将不起作用。 除此之外,我做了 davidhigh 建议的操作并返回 *this 而不是临时 Matrix 对象。

发生错误的语句是a *= c-c

首先,c-c 将创建一个 临时 对象。然后这个临时对象通过引用传递*= 操作符。 C++ 只允许将临时值传递给 const 引用、值或右值。

感谢大家帮助我。

【讨论】:

  • 不,更喜欢const Matrix&amp; 而不是Matrix(除非您要修改或移动参数)。
  • @aschepler 谢谢。我听从了你的建议,现在我认为它非常干净。在这里学到了很多。
  • 您还需要修复operator*= 以对*this 进行操作,而不是像您当前那样通过引用返回局部变量(另一个答案对此进行了描述)
  • 我已经提到了,对吧?修复需要应用于类中的所有运算符。实际上 davidhigh 提到了这个修复,但说这不是真正的问题。原来是这样。我会接受他的回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-15
  • 1970-01-01
  • 2018-04-26
  • 1970-01-01
  • 2012-08-02
相关资源
最近更新 更多