提问人:Sync it 提问时间:10/22/2020 更新时间:10/23/2020 访问量:180
C++ 添加 2 个 3D 矢量返回垃圾值
C++ adding 2 3D vectors returns garbage value
问:
我对 c++ 非常陌生,刚刚开始学习运算符重载。这是我的尝试
class Vector
{
public:
float x=0,y=0,z=0;
Vector(float x, float y, float z) :x(x),y(y),z(z) {}
Vector(Vector& copy) :x(copy.x),y(copy.y),z(copy.z){ std::cout << "Copy Created" << std::endl;} //Testing if any new objects were created during the operator overloading process[For my purpose this should not be called as no new objects should be created except than the returned result of each operator]
public:
Vector& operator+(Vector& v1) //return this+v1
{
Vector v(this->x+v1.x,this->y+v1.y,this->z+v1.z);
return v;
}
Vector& operator-(Vector& v1) //return this-v1
{
Vector v(this->x - v1.x, this->y - v1.y, this->z - v1.z);
return v;
}
Vector& operator*(Vector& v1) //return this cross v1
{
Vector v(this->y * v1.z-this->z * v1.y, -this->x * v1.z + this->z * v1.x, this->x * v1.y - this->y * v1.x);
return v;
}
}
std::ostream& operator<<(std::ostream& output, Vector& v)
{
output << v.x << "," << v.y << "," << v.z << std::endl;
return output;
}
int main()
{
Vector
v1(1, 2, 3),
v2(4, 5, 6);
Vector
v3 = v1 + v2,
v4 = v1 - v2,
v5 = v1 * v2;
std::cout << v3 << v4 << v5;
return 1;
}
打印时,所有 3 个向量都有垃圾值,并且每个操作调用了 copy 构造函数 3 次。我已经通过引用传递了每个向量,但仍然在我不理解的地方创建了一个新的临时实例。
我还尝试按照以前的线程的建议将关键字 const 添加到运算符及其参数中,但它并没有解决问题
由于我是新手,因此对解决方案的详细解释将不胜感激。谢谢
答:
不确定,但我认为您得到垃圾值是因为您试图返回对本地堆栈值 v 的引用。在重载运算符的作用域结束后,“v”值可能会被程序的另一部分覆盖。
可能的解决方案是:
Vector& operator+(Vector& v1) //return this+v1
{
return *new Vector(this->x+v1.x,this->y+v1.y,this->z+v1.z);
}
评论
delete
Vector
operator+
Vector
Vector
运算符 ,并通常返回副本而不是引用:+
*
-
Vector operator+(const Vector& v1) const
//^^ no &
//^^ added const
//^^ added const
{
Vector v(this->x+v1.x,this->y+v1.y,this->z+v1.z);
return v;
}
此外,您还应该将该方法声明为 ,以便您可以调用常量向量。参数应作为参考。const
operator+
const
有关运算符重载的更多详细信息,请参阅此处:运算符重载的基本规则和习语是什么?
在代码中,您返回的是对局部变量的引用,该变量总是错误的。一个简化的例子是
int& foo() {
int x = 0;
return x;
}
局部变量的生存期在函数返回并且调用方获得悬空引用时结束。使用该引用将调用未定义的行为。x
如果确实要避免副本,则应重载复合运算符 , , 。它们应就地执行操作,并且通常在修改操作后返回对操作的引用。有关详细信息,请参阅上面的链接。+=
*=
-=
this
我在上面写了“应该”、“通常”和“常规”。操作员过载相当灵活,可以做最奇怪的事情。但是,约定是从运算符 和 返回一个新值,并且返回对局部变量的引用总是错误的。+
*
-
最后但并非最不重要的一点是,我想提一下,看到一个初学者代码应用了如此少的不良做法,这令人耳目一新。除了你的错误,我唯一要批评的是一致性的正确性。默认生成方法和参数。仅当您需要修改它们时,才使它们非常量。例如,你也应该采取一个,因为它不会修改它。const
operator<<
const Vector&
评论
const
const
根据您的代码,我建议将运算符更改为 operator+= -= 和 *=。它们非常符合您的目的。在每个操作结束时,返回 *this。这意味着返回当前工作对象。例如:
vector& vector::operator+= (const vector& v)
{ this->x += v.x;
this->y += v.y;
this->z += v.z;
return *this;
}
并将 operator+ 写成两个参数的 friend 函数:
vector operator+(const vector&v1, const vector&v2)
{ vector v3(v1); // copy constructor
v3 += v2;
return v3;
}
下一个:在运算符重载中引用
评论
+
*
-
-Werror