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;
将编译而没有任何警告或错误(不知道矩阵是否正确,还没有检查过...)。
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您请求右侧参数是左值。它必须是现有变量,不能是临时值。考虑使用 const Matrix3D& m 代替。
Matrix3D ret = rotX*rotY*rotZ;
之所以有效,是因为它根本不使用operator=
,而是使用默认构造函数Matrix3D::Matrix3D(const Matrix3D&)
。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 usingoperator=
at all, instead it uses the default constructorMatrix3D::Matrix3D(const Matrix3D&)
.实际上,两个运算符都被错误地声明了。它们应该采用 const 引用以允许接受右值。
您会发现
*
不适用于rotX*(rotY*rotZ)
。Matrix3D ret = rotX*rotY*rotZ;
编译的原因是operator=
根本没有被调用。它只是调用 Matrix3D 的复制构造函数来获取乘法结果。乘法之所以有效,是因为rotX * rotY * rotZ
被重写为rotY
和rotZ
都是左值,因此它们可以绑定到Matrix3D&
。Actually, both operators are declared wrongly. They should take a
const
reference to allow rvalues be accepted.You'll see that
*
doesn't work withrotX*(rotY*rotZ)
.The reason
Matrix3D ret = rotX*rotY*rotZ;
compiles is because theoperator=
is not invoked at all. It just calls the copy constructor of Matrix3D to the result of the multiplication. And the multiplication works becauserotX * rotY * rotZ
is rewritten toand
rotY
androtZ
are both lvalues, so they can be bound toMatrix3D&
.operator*
和operator=
的正确声明:阅读材料:
你的
operator=
虽然rotX*rotY 接受
将产生一个右值,因此您无法将引用绑定到它。Matrix3D&
*rotX为了使工作正常,您的
operator=
应该接受Matrix3D const&
,它可以绑定到左值和右值 。尽管它可能看起来像
Obj a = b
使用Obj::operator=
但事实并非如此,它会使用通常称为复制构造函数的内容。 此处了解更多相关信息。Proper declarations of both
operator*
andoperator=
:Reading material:
Your
operator=
accepts aMatrix3D&
thoughrotX*rotY*rotX
will result in an rvalue and therefor you cannot bind a reference to it.To make work your
operator=
should accept aMatrix3D const&
, which can be bound to both lvalues and rvalues.Even though it may look like
Obj a = b
usesObj::operator=
it's not, it'll use what is normally referred to as the copy-constructor. Read more about it here.将赋值运算符的签名更改为常量正确:
在示例代码中,赋值运算符想要绑定到临时变量,而临时变量不能绑定到非常量引用。相比之下,由第二段代码调用的复制构造函数确实接受 const 引用,因此不会出现错误。
Change the signature of the assignment operator to be const-correct:
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.