hrs*_*rst 5 c++ reference vector
我在粒子系统中有一个名为Spring的类.构造函数看起来像:
Spring(Particle& _a, Particle& _b);
Run Code Online (Sandbox Code Playgroud)
我有一个粒子矢量,我使用
Spring mySpring = Spring(myParticles.at(j),myParticles.at(j+1));
Run Code Online (Sandbox Code Playgroud)
在一个循环内部,在两个粒子之间增加一个弹力.到目前为止一切正常.但是,我想使用粒子的2d矢量.那是:
Spring mySpring = Spring(myParticles.at(i).at(j),myParticles.at(i).at(j+1));
Run Code Online (Sandbox Code Playgroud)
而且我没有得到粒子的参考.在第一个例子中,每当我在spring类中更改粒子时,向量中的粒子都会发生变化.在第二个示例中,更改仅在本地进行.如何更改2D矢量中的粒子?
编辑:我试着说清楚一些事情:
我有一些粒子系统,每个粒子系统都由许多粒子组成.每个粒子只应与其自身处于同一系统中的其他粒子相互作用.因此,我有一个粒子系统向量,每个粒子系统都是粒子对象的向量.(这使得2d矢量).第一维(i)是系统,第二维(j)是单个粒子.系统中的粒子相互作用(碰撞,避免,等等......)并且它们的位置发生变化.矢量得到"更新".(即参考作品).
但是,我有第二个(1d)弹簧力矢量.弹簧力也用于更新颗粒的位置.我的构造函数执行以下操作:
Spring::Spring(Particle& _a, Particle& _b) {
a=&_a;
b=&_b; }
Run Code Online (Sandbox Code Playgroud)
a和b是粒子*.所以我存储指向2d向量中的两个粒子的指针.另一个函数Spring.doSpring()改变了粒子的位置.
a->pos.x=300;
Run Code Online (Sandbox Code Playgroud)
要么
a->velocity+=something..
Run Code Online (Sandbox Code Playgroud)
在我发布的第一个例子中,我只使用了一个粒子系统,因此不需要二维矢量.一切正常.向量中的粒子得到更新.但是第二个例子我的程序运行但不管doSpring函数做了什么,2d向量中的粒子都没有得到更新.
采用引用/指向向量内部元素的最常见问题之一是重新分配.例如,如果你使用push_back,那么向量将超过其容量,分配一个新的内存块,复制所有内容,然后释放旧块.如果您已经对向量中的元素进行了引用或指针,那么它们仍然指向旧块,现在是死记忆,并且是一个严重的错误!
所以我猜你的粒子效应会不断向你的粒子向量添加新的粒子,这在某些时候会导致向量在超出容量时重新分配.Spring类存储的指针虽然没有更新,但是指向死记忆并且对实际粒子没有影响,实际粒子被矢量移动到其他地方.
不要将引用或指针指向向量内的元素.使用指针,列表或其他容器的向量,它不会在实际元素的内存地址周围移动.如果必须,请使用迭代器到向量内的元素.在调试版本中,假设您已经检查了STL实现,如果在向量重新分配自身后通过迭代器访问该元素,您将获得调试警报.
小智 5
你正在做什么看起来没问题 - 下面的代码创建一个"2D"向量,并说明.at().at()构造确实给你一个引用:
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector <vector<int> > vi;
vi.push_back( vector <int>() );
vi.at(0).push_back( 42 );
cout << vi.at(0).at(0) << endl; // prints 42
vi.at(0).at(0) = 666;
cout << vi.at(0).at(0) << endl; // prints 666
}
Run Code Online (Sandbox Code Playgroud)
如果我理解正确的话,你想使用创建一个二维粒子数组std::vector
?
如果是这样,您可以将其声明为:std::vector<std::vector<Particle> >
。然后,您甚至可以使用[][]
命名法来访问元素。(危险威尔·罗宾逊!使用此操作符时不进行边界检查)
map
但是,如果这个 2D 数组主要包含零,那么使用带有索引作为键的a 可能是可以的。