I have a custom galaxy
class which has a custom property pos
.
pos
is an instance of another custom class Vector3D
.
A Vector3D
has properties x
, y
, z
. The arithmetic operations for Vector3D is basic vector math, the relevant ones below:
Vector3D Vector3D::operator (const Vector3D& vec) {
return Vector3D(x vec.x, y vec.y, z vec.z);
}
Vector3D &Vector3D::operator =(const Vector3D& vec) {
x = vec.x;
y = vec.y;
z = vec.z;
return *this;
}
Vector3D Vector3D::operator*(double val) {
return Vector3D(x * val, y * val, z * val);
}
galaxy.cpp has some methods below:
void galaxy::updatePos(double dt) {
pos = vel * dt;
}
void galaxy::updateVel(Vector3D accel, double dt) {
vel = accel * dt;
}
void galaxy::updateStateVectors(Vector3D accel, double dt) {
updateVel(accel, dt);
updatePos(dt);
}
main.cpp calls method updateStateVectors as follows:
// within some while() loop
for (auto g : galaxies) {
Vector3D accel = Vector3D();
for (auto g2 : galaxies) {
if (g != g2) {
accel = g.getGravityAccelBy(g2);
}
}
g.updateStateVectors(accel, dt);
}
(galaxies is a std::vector<galaxy>
)
The problem is, the changes made to g.pos (or g.vel) within this for loop doesn't seem to persist. Each iteration on the while loop, I see that g.pos is back to its original value, disregarding the change it previously underwent in the for loop. What am I missing?
This might end up being a very silly mistake but I mainly code in Python and I've spent more time on this than I'd like to admit.
CodePudding user response:
The loop for (auto g : galaxies) {
is creating a copy of elements of galaxies
to g
. Therefore, changes to g
are not saved to galaxies
.
You should use a reference to the elements like for (auto& g : galaxies) {
instead.
disclaimer:
I googled
site:stackoverflow.com [c ] range for not updated reference
site:stackoverflow.com [c ] range-based-for not updated reference
site:stackoverflow.com [c ] range-based-for not updated
site:stackoverflow.com [c ] range-based change value
but couldn't find a duplicate.
CodePudding user response:
auto returns a copy of the object, so the original one is copied, not modified. You're then altering a copy of the original object. Using & will make you reference the original one, so that you can alter it.
for (auto & g : galaxies) {
Vector3D accel = Vector3D();
for (auto & g2 : galaxies) {
if (g != g2) {
accel = g.getGravityAccelBy(g2);
}
}
g.updateStateVectors(accel, dt);
}
CodePudding user response:
Try to use this way to see if it works.
for (auto g& : galaxies) {
Vector3D accel = Vector3D();
for (auto g2 : galaxies) {
if (g != g2) {
accel = g.getGravityAccelBy(g2);
}
}
g.updateStateVectors(accel, dt);
}
bacause there is a temporary object(ex:temp_g) generated in for (auto g : galaxies)
, all changes are applied to the temporary object.