C++ 中奇怪的赋值/乘法运算符行为

发布于 2024-12-21 09:38:53 字数 2063 浏览 2 评论 0原文

有人可以解释一下我的运算符有什么问题吗:

Matrix3D Matrix3D::operator*(Matrix3D& m) {
    Matrix3D ret;
    for(int i=0;i<4;i++) {
        for(int j=0;j<4;j++) {
            ret._data[i][j]=0.0;
            for(int k=0;k<4;k++) {
                ret._data[i][j] += (this->_data[i][k]*m._data[k][j]);
            }
        }
    }
    return ret;
}

Matrix3D& Matrix3D::operator=(Matrix3D& m) {
    if(this==&m) {
        return *this;
    }
    for(int i=0;i<4;i++) {
        for(int j=0;j<4;j++) {
            this->_data[i][j] = m._data[i][j];
        }
    }
    return *this;
}

Matrix3D Matrix3D::Rotation(double ax, double ay, double az) {
    Matrix3D rotX;
    Matrix3D rotY;
    Matrix3D rotZ;
    rotX(
        1,          0,          0,          0,
        0,          cos(ax),    -sin(ax),   0,
        0,          sin(ax),    cos(ax),    0,
        0,          0,          0,          1
    );
    rotY(
        cos(ay),    0,          sin(ay),    0,
        0,          1,          0,          0,
        -sin(ay),   0,          cos(ay),    0,
        0,          0,          0,          1
    );
    rotZ(
        cos(az),    -sin(az),   0,          0,
        sin(az),    cos(az),    0,          0,
        0,          0,          1,          0,
        0,          0,          0,          1
    );

    // Matrix3D ret;
    // ret = rotX*rotY*rotZ;
    // This doesn't work
    // C:\(...)\Matrix3D.cpp|100|error: no match for 'operator=' in 'ret = Matrix3D::operator*(Matrix3D&)(((Matrix3D&)(& rotZ)))'|

    // however this does work

    Matrix3D ret = rotX*rotY*rotZ;
    return ret;
}

如上面的代码所述,类似的东西

    Matrix3D ret;
    ret = rotX*rotY*rotZ;

会导致

    C:\(...)\Matrix3D.cpp|100|error: no match for 'operator=' in 'ret = Matrix3D::operator*(Matrix3D&)(((Matrix3D&)(& rotZ)))'|

编译错误,而类似的东西

    Matrix3D ret = rotX*rotY*rotZ;

将编译而没有任何警告或错误(不知道矩阵是否正确,还没有检查过...)。

Could somebody please explain me wth is wrong with my operators:

Matrix3D Matrix3D::operator*(Matrix3D& m) {
    Matrix3D ret;
    for(int i=0;i<4;i++) {
        for(int j=0;j<4;j++) {
            ret._data[i][j]=0.0;
            for(int k=0;k<4;k++) {
                ret._data[i][j] += (this->_data[i][k]*m._data[k][j]);
            }
        }
    }
    return ret;
}

Matrix3D& Matrix3D::operator=(Matrix3D& m) {
    if(this==&m) {
        return *this;
    }
    for(int i=0;i<4;i++) {
        for(int j=0;j<4;j++) {
            this->_data[i][j] = m._data[i][j];
        }
    }
    return *this;
}

Matrix3D Matrix3D::Rotation(double ax, double ay, double az) {
    Matrix3D rotX;
    Matrix3D rotY;
    Matrix3D rotZ;
    rotX(
        1,          0,          0,          0,
        0,          cos(ax),    -sin(ax),   0,
        0,          sin(ax),    cos(ax),    0,
        0,          0,          0,          1
    );
    rotY(
        cos(ay),    0,          sin(ay),    0,
        0,          1,          0,          0,
        -sin(ay),   0,          cos(ay),    0,
        0,          0,          0,          1
    );
    rotZ(
        cos(az),    -sin(az),   0,          0,
        sin(az),    cos(az),    0,          0,
        0,          0,          1,          0,
        0,          0,          0,          1
    );

    // Matrix3D ret;
    // ret = rotX*rotY*rotZ;
    // This doesn't work
    // C:\(...)\Matrix3D.cpp|100|error: no match for 'operator=' in 'ret = Matrix3D::operator*(Matrix3D&)(((Matrix3D&)(& rotZ)))'|

    // however this does work

    Matrix3D ret = rotX*rotY*rotZ;
    return ret;
}

as stated in the code above, something like

    Matrix3D ret;
    ret = rotX*rotY*rotZ;

will result in

    C:\(...)\Matrix3D.cpp|100|error: no match for 'operator=' in 'ret = Matrix3D::operator*(Matrix3D&)(((Matrix3D&)(& rotZ)))'|

compilation error, while something like

    Matrix3D ret = rotX*rotY*rotZ;

will compile without any warning or error whatsoever (don't know if the matrixes are right tho, haven't checked that yet...).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一抹淡然 2024-12-28 09:38:54
Matrix3D& Matrix3D::operator=(Matrix3D& m)

您请求右侧参数是左值。它必须是现有变量,不能是临时值。考虑使用 const Matrix3D& m 代替。

Matrix3D ret = rotX*rotY*rotZ; 之所以有效,是因为它根本不使用 operator=,而是使用默认构造函数 Matrix3D::Matrix3D(const Matrix3D&)

Matrix3D& Matrix3D::operator=(Matrix3D& m)

You request that the right-side parameter is an l-value. It must be an existing variable, cannot be a temporary value. Consider using const Matrix3D& m instead.

The Matrix3D ret = rotX*rotY*rotZ; works because it is not using operator= at all, instead it uses the default constructor Matrix3D::Matrix3D(const Matrix3D&).

她比我温柔 2024-12-28 09:38:53

实际上,两个运算符都被错误地声明了。它们应该采用 const 引用以允许接受右值。

Matrix3D Matrix3D::operator*(const Matrix3D& m) const
//                           ^^^^^              ^^^^^
//                                              this too, since you're not
//                                              changing the LHS during '*'.

Matrix3D& Matrix3D::operator=(const Matrix3D& m)
//                            ^^^^^

您会发现 * 不适用于 rotX*(rotY*rotZ)

Matrix3D ret = rotX*rotY*rotZ; 编译的原因是 operator= 根本没有被调用。它只是调用 Matrix3D 的复制构造函数来获取乘法结果。乘法之所以有效,是因为 rotX * rotY * rotZ 被重写为

rotX.operator*(rotY).operator*(rotZ)

rotYrotZ 都是左值,因此它们可以绑定到 Matrix3D&

Actually, both operators are declared wrongly. They should take a const reference to allow rvalues be accepted.

Matrix3D Matrix3D::operator*(const Matrix3D& m) const
//                           ^^^^^              ^^^^^
//                                              this too, since you're not
//                                              changing the LHS during '*'.

Matrix3D& Matrix3D::operator=(const Matrix3D& m)
//                            ^^^^^

You'll see that * doesn't work with rotX*(rotY*rotZ).

The reason Matrix3D ret = rotX*rotY*rotZ; compiles is because the operator= is not invoked at all. It just calls the copy constructor of Matrix3D to the result of the multiplication. And the multiplication works because rotX * rotY * rotZ is rewritten to

rotX.operator*(rotY).operator*(rotZ)

and rotY and rotZ are both lvalues, so they can be bound to Matrix3D&.

魔法唧唧 2024-12-28 09:38:53

operator*operator= 的正确声明:

Matrix3D  Matrix3D::operator* (Matrix3D const& m) const;
Matrix3D& Matrix3D::operator= (Matrix3D const& m);

阅读材料:


你的 operator= 虽然 rotX*rotY 接受 Matrix3D& *rotX 将产生一个右值,因此您无法将引用绑定到它。

为了使工作正常,您的 operator= 应该接受 Matrix3D const&,它可以绑定到左值右值

尽管它可能看起来像 Obj a = b 使用 Obj::operator= 但事实并非如此,它会使用通常称为复制构造函数的内容。 此处了解更多相关信息。

Proper declarations of both operator* and operator=:

Matrix3D  Matrix3D::operator* (Matrix3D const& m) const;
Matrix3D& Matrix3D::operator= (Matrix3D const& m);

Reading material:


Your operator= accepts a Matrix3D& though rotX*rotY*rotX will result in an rvalue and therefor you cannot bind a reference to it.

To make work your operator= should accept a Matrix3D const&, which can be bound to both lvalues and rvalues.

Even though it may look like Obj a = b uses Obj::operator= it's not, it'll use what is normally referred to as the copy-constructor. Read more about it here.

入画浅相思 2024-12-28 09:38:53

将赋值运算符的签名更改为常量正确:

Matrix3D& Matrix3D::operator=(Matrix3D const & m)
//                                     ^^^^^

在示例代码中,赋值运算符想要绑定到临时变量,而临时变量不能绑定到非常量引用。相比之下,由第二段代码调用的复制构造函数确实接受 const 引用,因此不会出现错误。

Change the signature of the assignment operator to be const-correct:

Matrix3D& Matrix3D::operator=(Matrix3D const & m)
//                                     ^^^^^

In your example code, the assignment operator wants to bind to a temporary, and temporaries cannot bind to non-constant references. By contrast, the copy constructor, which is invoked by the second piece of code, does accept a const reference, so there's no error.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文