У меня есть пользовательский класс galaxy
, у которого есть настраиваемое свойство pos
.
pos
является экземпляром другого пользовательского класса Vector3D
.
Vector3D
имеет свойства x
, y
, z
. Арифметические операции для Vector3D — это базовая векторная математика, соответствующие ниже:
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 имеет несколько методов ниже:
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 вызывает метод updateStateVectors следующим образом:
// 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);
}
(галактики это std::vector<galaxy>
)
Проблема в том, что изменения, внесенные в g.pos (или g.vel) в этом цикле for, похоже, не сохраняются. На каждой итерации цикла while я вижу, что g.pos возвращается к своему исходному значению, несмотря на изменения, которые он ранее претерпел в цикле for. Что мне не хватает?
Это может оказаться очень глупой ошибкой, но я в основном программирую на Python и потратил на это больше времени, чем хотел бы признать.
auto возвращает копию объекта, поэтому исходным является скопировано, не измененный. Затем вы изменяете копировать исходного объекта. Использование & заставит вас сослаться на оригинальный, чтобы вы могли его изменить.
for (auto & g : galaxies) {
Vector3D accel = Vector3D();
for (auto & g2 : galaxies) {
if (g != g2) {
accel += g.getGravityAccelBy(g2);
}
}
g.updateStateVectors(accel, dt);
}
Цикл for (auto g : galaxies) {
создает копию элементов из galaxies
в g
. Поэтому изменения в g
не сохраняются в galaxies
.
Вместо этого вы должны использовать ссылку на такие элементы, как for (auto& g : galaxies) {
.
отказ от ответственности:
я гуглил
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
но не смог найти дубликат.
Попробуйте использовать этот способ, чтобы увидеть, работает ли он.
for (auto g& : galaxies) {
Vector3D accel = Vector3D();
for (auto g2 : galaxies) {
if (g != g2) {
accel += g.getGravityAccelBy(g2);
}
}
g.updateStateVectors(accel, dt);
}
поскольку в for (auto g: galaxies)
создан временный объект (например: temp_g), все изменения применяются к временному объекту.
Вы должны использовать ссылку. Измените auto g на auto& g, то же самое для g2