0

for some vector arithmetics in 3 dimensions I defined a vector class with consturctors and I try to overload some operators:

class Vector3{
public:

typedef double d_type;
d_type x,y,z;
Vector3(d_type d_x, d_type d_y, d_type d_z){x = d_x; y = d_y; z = d_z;}
Vector3(){x=0;y=0;z=0;}

Vector3 operator +( Vector3 &v){return Vector3(this->x + v.x, this->y + v.y, this->z + v.z);}
Vector3 operator -( Vector3 &v){return Vector3(this->x - v.x, this->y - v.y, this->z - v.z);}


Vector3 operator +=( Vector3 &v){return Vector3(this->x += v.x, this->y += v.y, this->z += v.z);}
Vector3 operator -=( Vector3 &v){return Vector3(this->x -= v.x, this->y -= v.y, this->z -= v.z);}

};

if I understand it right, "&v" is a call by reference, only a reference is put on the stack, not the whole object Vector3 v. Is *v also possible as a call by reference? I have seen some other versions like:

      inline Vector3 operator+(const Vector3& u, const Vector3& v)  
       {return Vector3(u.x + v.x, u.y + v.y,u.z + v.z);}
      inline Vector3 operator-(const Vector3& v)    
       {return Vector3(-v.x, -v.y, -v.z);}

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

Why use "inline" and "const"? does it give a runtime boost? Is there a difference between "Vector3& v" and "Vector3 &v"? What are the advantages and disadvanteages of overloading the operators in that kind of way?

Moritz123
  • 3
  • 1
  • 2
    One question by question. – Jarod42 Apr 15 '21 at 15:56
  • 1
    `Vector3 operator +=` -- Why are you returning a new object? This should be returning a reference to the existing object, as in the second version you posted. – PaulMcKenzie Apr 15 '21 at 15:58
  • 1
    `Vector3* v` is a pointer. `inline` is for ODR and useless in class definition. `const` is to help programmer. No runtime boost, place of `&` near type or variable is stylistic. – Jarod42 Apr 15 '21 at 15:59
  • 1
    BTW, you only need the `this->` notation when differentiating between parameter names and member variable names. Not using the notation means fewer typos and less typing time. – Thomas Matthews Apr 15 '21 at 16:04
  • 1
    Does this answer your question? [What are the basic rules and idioms for operator overloading?](https://stackoverflow.com/questions/4421706/what-are-the-basic-rules-and-idioms-for-operator-overloading) – Richard Critten Apr 15 '21 at 16:04
  • 1
    Instead of a new vector class, I recommend creating a 3d point class and having a vector of 3d point instances. – Thomas Matthews Apr 15 '21 at 16:05
  • 1
    Search the internet for "C++ FAQ operator overloading" or "C++ Scott Meyers operator overloading". – Thomas Matthews Apr 15 '21 at 16:06

1 Answers1

0

First, the idea of "pass by reference" is slightly muddled in c++ because there are pointers and references, and both allow the idea, but due to naming it can be misconstrued, and misunderstandings can happen when people communicate. But you can "pass by reference" without using "references", insofar as you are not passing a copy of the object, and changes through the argument can affect the caller's object.

A member declared like this:

Vector3 operator +( Vector3 &v);

Indeed takes an lvalue reference to v, so no copy is made. However, in C++, a function that takes a non-const reference to a parameter is advertising, "I plan to possibly change this object." If that's not the case, then you should change the signature to this:

Vector3 operator + (Vector3 const& v);

Also, if you have rvalues, they can bind to references-to-const object, but cannot bind to references-to-nonconst objects. The idea is, mutating a temporary object is usually a mistake, so the language doesn't let you. (And if you really want to do that, you cause take an rvalue-reference.

As for inline, that is only necessary if you plan to define the function in a header, and it is defined outside the class body. The keyword is less about performance, and more about how the object code is generated, so that the linker won't complain if it sees multiple copies of the function. (If a.cpp, b.cpp, and c.cpp each include your header that defines a function, you end up with a copy of the function in each translation unit, and if they weren't "inline", their "linkage" would require a single definition, and the linker would see multiple and complain about multiply defined function. With inline, the linker does not complain, but merely picks an implementation (since they're all the same) and uses it.

As for your return value question, this is not a good signature to use:

Vector3 operator +=( Vector3 &v);

It should be:

Vector3& operator +=( Vector3 const& v);

Const is described above, and the return value being a reference allows no temporary object construction for the return value, and also you can "chain" calls together. Since operator+= modifies the object it's called on, the normal return value for this function is to return *this.

Chris Uzdavinis
  • 6,022
  • 9
  • 16