So I've been writing a small math library in C++ and when dealing with a scalar multiplied by a vector I get some issues when I try to perform this operation
Vect V2;
Vect V3;
float S;
Vect V1 = V2 + S * (V2 - V3);
The Vect Value I receive in the overloaded operator * is a new Vect object and not the outcome of the (V2 - V3) part of the operation. Here's the other relevant part of the code. If I follow the operation with the debugging the two overloaded operators work correctly by themselves but not one after the other.
Vect.h
Vect &operator - (const Vect &inVect);
friend const Vect operator*(const float scale, const Vect &inVect);
Vect.cpp
Vect &Vect::operator - (const Vect &inVect)
{
return Vect (this->x - inVect.x,this->y - inVect.y,this->z - inVect.z, 1);
}
const Vect operator*(const float scale, const Vect &inVect)
{
Vect result;
result.x = InVect.x * scale;
result.z = InVect.y * scale;
result.y = InVect.z * scale;
result.w = 1;
return result;
}
I also overloaded the + and = operator and they work as expected the only problem I encounter is the problem above.
In your operator-, you create a temporary Vect and return a reference to that temporary. The temporary is destroyed at the end of the return statement and the returned reference is left dangling. Doing anything with this reference will result in undefined behaviour.
Instead, your operator- should return a Vect by value:
Vect Vect::operator - (const Vect &inVect)
{
return Vect (this->x - inVect.x,this->y - inVect.y,this->z - inVect.z, 1);
}
Related
I am trying to do a multiplication for my vector class and my matrix class.
Vector2f Matrix3x3::operator * (Vector2f & v) {
float vx = e11 * v.x + e21 * v.y + e31;
float vy = e12 * v.x + e22 * v.y + e32;
return Vector2f(vx, vy);
}
When a matrix multiplies with a vector it should return a vector. So I try to set the result to an already created vector object.
Vector2f d(12, 12);
Matrix3x3 m = translationMatrix(transX, transY);
d = m * d;
VS keeps underlining my "=" and says that no operators = match these operands, operands type are Vector2f and Vector2f. Even though I already overload assignment operator in Vector2f class
Vector2f & Vector2f::operator = (Vector2f & V) {
x = V.x;
y = V.y;
return *this;
}
I dont even know where I am wrong. Can someone explain it to me?
Matrix3x3::operator * returns by value, which means the object returned by m * d is a temporary, which can't be bound to lvalue-reference to non-const (i.e. Vector2f &); but it can be bound to lvalue-reference to const (i.e. const Vector2f &).
To solve the issue you chould change the parameter type of operator= to const Vector2f &, and you should do this also because the argument is supposed to be not modified inside operator=.
Vector2f & Vector2f::operator = (const Vector2f & V) {
x = V.x;
y = V.y;
return *this;
}
I am making a module/library with a vector class, and I want it to do it properly.
class Vector3 {
public:
float x, y, z;
public:
Vector3();
Vector3(float a, float b, float c);
float length();
void normalize();
Vector3* dotproduct(Vector3 *rhs);
Vector3* crossproduct(Vector3 *rhs);
Vector3* add(Vector3 *rhs);
Vector3* subtract(Vector3 *rhs);
};
My doubt is in how should I return a new Vector3 after an operation.
Currently, I am dynamically allocating a new Vector3 inside each operation and then I return it.
When I use the operation I have:
Vector3 *v = v2->crossproduct(v3);
Should I change my operations to:
Vector3 Vector3::crossproduct(Vector3 *rhs){
float a = y * rhs->z - z * rhs->y;
float b = z * rhs->x - x * rhs->z;
float c = x * rhs->y - y * rhs->x;
Vector3 res(a, b, c);
return res ;
}
And use:
Vector3 v = v2->crossproduct(v3);
Or will I eventually lose the vector?
Since I'm trying to make a library what is the proper way to do it?
Allocate at the stack, or in the heap?
I implemente these operations like this:
Vector3 Vector3::crossproduct(const Vector3& rhs){
float a = y * rhs.z - z * rhs.y;
float b = z * rhs.x - x * rhs.z;
float c = x * rhs.y - y * rhs.x;
Vector3 res(a, b, c);
return res ;
}
To use this operator you can simply use this syntax:
Vector v1, v2;
auto product = v1.crossproduct(v2);
The return as value is most likely optimized away by copy elision, so you dont have to worry about that. And since rhs is not modified, passing it as const ref& is the fastest way to do it.
I was once using Unity and they use a cool System to add and multiply vectors.
This is a short excerpt from the Reference (http://docs.unity3d.com/ScriptReference/Transform.html)
foreach (Transform child in transform) {
child.position += Vector3.up * 10.0F;
}
as you can see they can just add and multiply two Vectors (structs/classes) even though they could have different variables. Right now when I try to make such a calculation I have to add the x and y of a 2d float vector individually.
So how can i add structs like a
struct Vec2f{
float x;
float y;
};
together by writing
Vec2f c = a + b;
instead of
c.x = a.x + b.x;
c.y = a.y + b.y;
EDIT:
You need to overload operators like '+', '-' etc. in your struct. Example for addition:
struct Vec2f
{
float x;
float y;
Vec2f operator+(const Vec2f& other) const
{
Vec2f result;
result.x = x + other.x;
result.y = y + other.y;
return result;
}
};
EDIT 2:
RIJIK asks in comment:
Also i wonder if there are some tricks to make the functions not to be so repetetive. I mean if i now want to use an operator i have to make a function for each operator even if there is no big difference between the functions besides the operator which is used. How do you approach in implementing calculations or many operators?
So one thing you can do is use another operators in operator. Something like you can change subtraction to addition, by simply negate second number:
a - b becomes a + (-b)
Of course you need negation operator first in your struct to do that. Example code:
struct Vec2f
{
float x;
float y;
Vec2f operator+(const Vec2f& other) const
{
Vec2f result;
result.x = x + other.x;
result.y = y + other.y;
return result;
}
Vec2f operator-() const
{
Vec2f result;
result.x = -x;
result.y = -y;
return result;
}
// we use two operators from above to define this
Vec2f operator-(const Vec2f& other) const
{
return (*this + (-other));
}
};
One nice thing about this is that if you change addition for example than you don't need to change subtraction. It is changed automatically.
And as reply to this:
But i don't understand why i should make the functions constant.
Because then you can use this function with constant variables. For example:
const Vec2f screenSize = { 800.0f, 600.0f };
const Vec2f boxSize = { 100.0f, 200.0f };
const Vec2f sub = screenSize - boxSize;
I am using here also curly braces initialization, cause you don't define any constructor.
I wrote a class like this:
class vector3D{
public:
double x,y,z;
}
and i overload + operator:
class vector3D{
public:
double x,y,z;
vector3D operator+(const vector3D &lhs)
{
vector3D temp(x+lhs.x,y+lhs.y,z+lhs.z);
return temp;
}
}
but using C=A+B is slower than
C.x = A.x + B.x;
C.y = A.y + B.y;
C.z = A.z + B.z;
i think it is because defining a vector3D instance in + overloading function. is there anyway to avoid this?
(FYI: i build with this flags: -Wall -Wextra -Wunreachable-code -m32 -DNDEBUG -O2 -D_LARGEFILE64_SOURCE -D_REETRANT -D_THREAD_SAFE)
EDIT:
this is how i test speed of two approach(in main() ):
//test bench
vector3D A(0.0,0.0,0.0), B(1e-9,1e-9,1e-9);
clock_t c = clock();
//case A
for(long int i=0;i<1000000000;i++)
{
A = A + B;
}
cout<<"case A took: "<<1.0*(clock()-c)/CLOCKS_PER_SEC<<A<<endl;
c = clock();
//case B
for(long int i=0;i<1000000000;i++)
{
A._x = A._x+B._x;
A._y = A._x+B._y;
A._z = A._x+B._z;
}
cout<<"case B took: "<<1.0*(clock()-c)/CLOCKS_PER_SEC<<A<<endl;
and the result is:
case A took: 5.539[1, 1, 1]
case B took: 1.531[2, 2, 2]
Since you're creating an additional object, it will carry some overhead. This is inherent.
However, looking at the "payload lines" you want, they are very similar to what you'd have in the body of operator+= adding some other:
vector3D &operator+=(const vector3D &other) // Note - no objects created.
{
x += other.x;
y += other.y;
z += other.z;
return *this; // Note - return by reference.
}
Of course, operator+= modifies its left operand (which is exactly why you have operator+ with its object-creation overhead).
In general, you should prefer operator+= for heavy objects where it is applicable (see also this question).
You may actually get a performance boost by collapsing this to one line and taking advantage of return value optimization:
vector3D operator+(const vector3D &lhs)
{
return vector3D(x+lhs.x,y+lhs.y,z+lhs.z);
}
I was looking over some code, in a textbook and they wrote:
Vector3 &operator =(const Vector3 &a) {
x = a.x; y = a.y; z = a.z;
return *this;
}
Does the following code produce the same, returning the type, not a reference to it(they both run):
Vector3 operator =(const Vector3 &a) {
x = a.x; y = a.y; z = a.z;
return *this;
}
my question: what is the difference between the two?
thanks
daniel
Vector3 a, b;
(a = b).x = 3;
In this code, a.x should end up with the value of 3. In the second example you give, that won't happen.
Vector3 b(1,2,3);
Vector3 a;
(a = b).x += 2.0;
Print(a.x);
If you use operator returning refernce, above code should print 3.0
In case of operator returning value it would print 1.0