1

I have a Vector3 class that has + and * operators overloaded as follows:

Vector3& operator+ (Vector3& v1, Vector3& v2)
{
    Vector3 sum = Vector3(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
    static Vector3& ref = sum;
    return ref;
}

Vector3& operator* (Vector3& v1, double value)
{
    Vector3 product = Vector3(v1.x * value, v1.y * value, v1.z * value);
    static Vector3& ref = product;
    return ref;
}

Vector3& operator* (double value, Vector3& v1)
{
    Vector3 product = Vector3(v1.x * value, v1.y * value, v1.z * value);
    static Vector3& ref = product;
    return ref;
}

But when calculating a linear combination of 2 vectors v1 and v2, I get 2 different results when done separately vs in one line:

#include <iostream>
#include "Vector3.h"
using namespace std;

int main()
{
    Vector3 v1 = Vector3(1.0, 2.0, 3.0);
    Vector3 v2 = Vector3(2, 2, 2);

    Vector3 v3 = v1 * -1;
    Vector3 v4 = v2 * 1.2;

    cout << v3 + v4 << endl;

    cout << (v1 * -1.0) + (v2 * 1.2) << endl;

    return 0;
}

Output:

(1.4, 0.4, -0.6)
(-2, -4, -6)
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
StealthyPanda
  • 85
  • 1
  • 4

1 Answers1

5

Your code has undefined behavior, anything is possible. The reference ref and returned reference refer to local object sum and product, which will be destroyed when get out of the function, left the returned reference dangling. Dereference on them leads to UB.

operator+ and operator* are supposed to return by-value.

Vector3 operator+ (const Vector3& v1, const Vector3& v2)
{
    return Vector3(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
}

Vector3 operator* (const Vector3& v1, double value)
{
    return Vector3(v1.x * value, v1.y * value, v1.z * value);
}

Vector3 operator* (double value, const Vector3& v1)
{
    return Vector3(v1.x * value, v1.y * value, v1.z * value);
    // or 
    // return v1 * value;
}

BTW: I changed the operators taking Vector3 as reference to const, which works with temporaries too.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • I did actually implement it this way initially, however that leads to the problem that chaining operations leads to a really nasty error message that cant even comprehend. For example this line: cout << (v1 * -1.0) + (v2 * 1.2) << endl; causes an error. – StealthyPanda Jul 30 '21 at 07:21
  • 3
    @StealthyPanda Most likely because your versions of the operators take the arguments by non-const reference, which is also wrong. – Sebastian Redl Jul 30 '21 at 07:21