C++中奇怪的赋值/乘法运算符行为
Strange assignment / multiplication operator behaviour in C++
有人可以解释一下我的运算符有问题吗:
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;
将在没有任何警告或错误的情况下编译(不知道矩阵是否正确,还没有检查过......
实际上,这两个运算符都被错误地声明了。它们应采用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)
rotY
和rotZ
都是左值,因此它们可以绑定到Matrix3D&
。
operator*
和operator=
的正确声明:
Matrix3D Matrix3D::operator* (Matrix3D const& m) const;
Matrix3D& Matrix3D::operator= (Matrix3D const& m);
阅读材料:
- 什么是左值/右值?
- 什么是常量正确性,为什么 ::operator* 应该是恒量?
您的operator=
接受Matrix3D&
尽管rotX*rotY*rotX
会产生右值,因此您无法绑定对它的引用。
为了使工作,你的operator=
应该接受一个Matrix3D const&
,它可以绑定到左值和右值。
即使它看起来像Obj a = b
使用Obj::operator=
它不是,它也将使用通常称为复制构造函数的东西。在此处阅读更多相关信息。
将赋值运算符的签名更改为 const-correct:
Matrix3D& Matrix3D::operator=(Matrix3D const & m)
// ^^^^^
在示例代码中,赋值运算符想要绑定到临时引用,而临时运算符无法绑定到非常量引用。相比之下,由第二段代码调用的复制构造函数确实接受 const 引用,因此没有错误。
Matrix3D& Matrix3D::operator=(Matrix3D& m)
您请求右侧参数为 l 值。它必须是现有变量,不能是临时值。请考虑改用const Matrix3D& m
。
该Matrix3D ret = rotX*rotY*rotZ;
之所以有效,是因为它根本不使用operator=
,而是使用默认的构造函数Matrix3D::Matrix3D(const Matrix3D&)
。
- 重载Singly Linked List中的赋值运算符
- 使用赋值运算符重载从类中返回jobject
- 标准库类型的赋值运算符的引用限定符
- 复制构造函数、赋值运算符C++
- 标准::变体的赋值运算符
- 移动赋值运算符;尝试引用已删除的函数.我该如何解决这个问题?
- 基类和派生类的多态赋值运算符
- 为用户定义的类正确调用复制构造函数/赋值运算符
- CRTP 中的复制赋值运算符 - gcc vs clang 和 msvc
- 为什么初始化时没有调用重载赋值运算符?
- 赋值运算符重载和自赋值
- C++矢量复制构造函数和赋值运算符是否也复制保留空间?
- Qt PL/SQL - 赋值运算符 - 字符串缓冲区太小
- 使用 OR 运算符赋值
- 交换与使用std::map[]运算符赋值(const问题)
- 为什么派生类不使用基类运算符=(赋值运算符)?
- 如何解决VC++2012生成运算符=赋值和复制构造函数的错误
- 商运算符赋值
- 使用重载的下标运算符赋值
- 在移动运算符/赋值运算符中,我应该使用std::move还是std::forward