C++ 添加 2 个 3D 向量 returns 垃圾值

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 个向量都有垃圾值,并且每个操作调用复制构造函数 3 次。我已经通过引用传递了每个向量,但仍然在我不理解的地方创建了一个新的临时实例。

我也试过按照之前帖子的建议将关键字 const 添加到运算符及其参数,但它没有解决问题

由于我是新手,因此将不胜感激对解决方案的详尽解释。谢谢

不确定,但我认为你得到垃圾值是因为你试图 return 引用本地堆栈值 v。在你重载运算符的范围结束后,'v' 值可能会被另一个覆盖程序的一部分。

可能的解决方案是:

Vector& operator+(Vector& v1) //return this+v1
{
    return *new Vector(this->x+v1.x,this->y+v1.y,this->z+v1.z);
}

运算符 +*- 通常 return 复制而非参考:

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参考。

有关运算符重载的更多详细信息,请参见此处:What are the basic rules and idioms for operator overloading?

在您的代码中,您return引用了一个总是错误的局部变量。一个简化的例子是

int& foo() {
   int x = 0;
   return x;
}

局部变量 x 的生命周期在函数 returns 和调用者获得悬空引用时结束。使用该引用调用 undefined behavior.

如果您确实想避免复制,您应该重载复合运算符 +=*=-=。他们应该执行 in-place 操作,通常 return 在修改后引用 this。详情见上文link.

我在上面写了“应该”、“通常”和“通常”。运算符重载相当灵活,可以做最奇怪的事情。但是,惯例是 return 来自运算符 +*- 的新值,并且 return 对局部变量的引用总是错误的。

最后但并非最不重要的一点是,我想提一下,看到初学者代码应用了如此少的不良做法令人耳目一新。除了你的错误,我唯一要批评的是 const 正确性。默认情况下使方法和参数const。仅当您需要修改它们时才使它们 non-const。例如,您的 operator<< 也应该采用 const Vector&,因为它不会对其进行修改。

根据您的代码,我建议您将运算符更改为运算符+= -= 和 *=。它们非常适合您的目的。在每次操作结束时,return *this。意思是returning当前工作对象。例如:

vector& vector::operator+= (const vector& v) 
 { this->x += v.x;
   this->y += v.y;
   this->z += v.z;
   return *this; 
 }

并将 operator+ 编写为两个参数的友元函数:

 vector operator+(const vector&v1, const vector&v2)
  { vector v3(v1);  // copy constructor
    v3 += v2;
    return v3;
  }