我想做这样的事情:
Matrix m; // (4x4 matrix)
Vector4 v; // (4-elements vector)
m(0) = v; // replace first 4-elements matrix row by vector v
v = m(0); // replace vector v by first 4-elements matrix row
继承我的代码:
Vector4& Matrix::operator() (unsigned row)
{
return Vector4(mat[row][0], mat[row][1], mat[row][2], mat[row][3]);
}
Vector4 Matrix::operator() (unsigned row) const
{
return Vector4(mat[row][0], mat[row][1], mat[row][2], mat[row][3]);
}
第二个运算符工作正常,但是当我尝试编译第一个运算符时,我收到此错误:
错误:从'Vector4'类型的右值开始无效初始化'Vector4&'类型的非const引用
问题出在哪里?在这种情况下,重载operator()而不是operator []是个好主意?
通过从矩阵中只获取一个元素,我使用另外两个运算符:
float& Matrix::operator() (unsigned row, unsigned col)
{
return mat[row][col];
}
float Matrix::operator() (unsigned row, unsigned col) const
{
return mat[row][col];
}
我想我找到了一些解决方案。第一个运算符已替换为:
Matrix::MatrixHelper operator() (unsigned row)
{
MatrixHelper m;
m.f1 = &mat[row][0];
m.f2 = &mat[row][1];
m.f3 = &mat[row][2];
m.f4 = &mat[row][3];
return m;
}
继承了MatrixHelper类的定义:
class MatrixHelper
{
public:
friend class Matrix;
void operator= (const Vector4& v)
{
*f1 = v.x;
*f2 = v.y;
*f3 = v.z;
*f4 = v.w;
}
private:
float* f1;
float* f2;
float* f3;
float* f4;
};
现在可以做类似的事情:
m(0) = Vector4(3,3,3,3);
但是在调用它时会出现新问题:
(m)(0) * someScalar;
从不调用第二个运算符,所以我必须在我的MatrixHelper类中实现它们吧?我走在正确的轨道上?
如果两个运营商同时工作,那么问题就解决了。但现在只能启用其中一个。我无法理解为什么总是使用第一个运算符,例如使用此代码(只需示例):
Vector4& Matrix::operator() (unsigned row)
{
std::cout << "Operator one is working now\n";
}
Vector4 Matrix::operator() (unsigned row) const
{
std::cout << "Operator two is working now\n";
}
无论我在做什么
m(0)=向量(4,4,4,4)
或
Vector4 v = m(0)
始终是第一个运营商。为什么呢?
我找到了其他一些解决方案。现在一切正常,但性能可能有点问题。解决方案没有以我想要的方式解决,这有点牵强。这是代码:
算:
Vector4 Matrix::operator() (unsigned row)
{
return Vector4 (&mat[row][0], &mat[row][1], &mat[row][2], &mat[row][3]);
}
Vector4 Matrix::operator() (unsigned row) const
{
return Vector4 (mat[row][0], mat[row][1], mat[row][2], mat[row][3]);
}
你可以看到第一个运算符返回一个带指针的向量。现在在Vector4类而不是Matrix中进行了艰苦的工作。 Vector4现在有了一个额外的构造函数:
Vector4(float* x, float* y, float* z, float* w)
{
this->px = x; this->py = y; this->pz = z; this->pw = w;
this->x = *x; this->y = *y; this->z = *z; this->w = *w;
pointer = true;
}
第一行是指针,第二行是变量,第三行是布尔类型变量,表示调用了什么构造函数(正常或指针)。
现在是最后一个运算符(operator =):
Vector4 operator= ( const Vector4& v)
{
if ( pointer )
{
*px = x = v.x;
*py = y = v.y;
*pz = z = v.z;
*pw = w = v.w;
}
else
{
x = v.x;
y = v.y;
z = v.z;
w = v.w;
}
}
如果pointer
为真,则表示 - px
,py
,pz
和pw
是指向矩阵中某些行元素的指针,我们必须改变它们。否则 - 只是正常的矢量。
所以现在问题......这是糟糕的坏解决方案,还是只是糟糕? :d
答案 0 :(得分:2)
您在错误代码中实例化的Vector4
是一个临时的r值。除了你不能将它分配给非const引用之外,当你的函数退出并且返回值是无效的堆栈位置时它将被销毁。
一种解决方案是按值返回不同的对象,该值存储对所需单个元素的引用,并允许您以透明的方式对其进行操作。