简体   繁体   English

参考2d向量中的元素(c ++)

[英]Reference to element in 2d vector (c++)

I have a class named Spring in a particle system. 我在粒子系统中有一个名为Spring的类。 The constructor looks like: 构造函数看起来像:

Spring(Particle& _a, Particle& _b);

And I have a vector of Particles and I use 我有一个粒子矢量,我使用

Spring mySpring = Spring(myParticles.at(j),myParticles.at(j+1));

inside a loop to add a spring force between two particles. 在一个循环内部,在两个粒子之间增加一个弹力。 Everything works fine so far. 到目前为止一切正常。 However, I want to use a 2d vector of Particles. 但是,我想使用粒子的2d矢量。 That is: 那是:

Spring mySpring = Spring(myParticles.at(i).at(j),myParticles.at(i).at(j+1));

And I don't get a reference to the particle. 而且我没有得到粒子的参考。 In the first example, whenever I change the particle in my spring class, the particle in the vector gets changed. 在第一个例子中,每当我在spring类中更改粒子时,向量中的粒子都会发生变化。 In the second example the changes are only locally. 在第二个示例中,更改仅在本地进行。 How can I change the particles in the 2D Vector? 如何更改2D矢量中的粒子?

EDIT: I try to make some things clear: 编辑:我试着说清楚一些事情:

I have some particle systems and each of them consists of a number of particles. 我有一些粒子系统,每个粒子系统都由许多粒子组成。 Each particle should only interact with the other particles that are in the same system as itself. 每个粒子只应与其自身处于同一系统中的其他粒子相互作用。 Therefore I have a vector of particle systems with each particle sytem being a vector of particle objects. 因此,我有一个粒子系统向量,每个粒子系统都是粒子对象的向量。 (That makes the 2d vector). (这使得2d矢量)。 The first dimension (i) is the system, the second (j) the individual particle. 第一维(i)是系统,第二维(j)是单个粒子。 The particles in the system interact with each other (collide, avoid, whatever..) and their positions change. 系统中的粒子相互作用(碰撞,避免,等等......)并且它们的位置发生变化。 And the vector gets "updated". 矢量得到“更新”。 (That is, the reference works). (即参考作品)。

However, i have a second (1d) vector of spring forces. 但是,我有第二个(1d)弹簧力矢量。 The spring force too is used to update the positions of the particles. 弹簧力也用于更新颗粒的位置。 My constructor does the following: 我的构造函数执行以下操作:

Spring::Spring(Particle& _a, Particle& _b) {
    a=&_a;
    b=&_b; }

With a and b being Particle*. a和b是粒子*。 So i store pointers to two particles in the 2d vector. 所以我存储指向2d向量中的两个粒子的指针。 Another function Spring.doSpring() changes the positions of the particles. 另一个函数Spring.doSpring()改变了粒子的位置。

a->pos.x=300;

or 要么

a->velocity+=something..

In the first example I posted I used only one particle system and so there was no need for a 2d vector. 在我发布的第一个例子中,我只使用了一个粒子系统,因此不需要二维矢量。 And everything works fine. 一切正常。 The particles in the vector gets updated. 向量中的粒子得到更新。 But with the second example my program runs but somehow no matter what the doSpring function does, the particles in the 2d vector don't get updated. 但是第二个例子我的程序运行但不管doSpring函数做了什么,2d向量中的粒子都没有得到更新。

One of the most common issues taking references/pointers to elements inside vectors is reallocation. 采用引用/指向向量内部元素的最常见问题之一是重新分配。 If you push_back, for example, it's possible the vector will exceed its capacity, allocate a new block of memory, copy everything over, then free the old block. 例如,如果你使用push_back,那么向量将超过其容量,分配一个新的内存块,复制所有内容,然后释放旧块。 If you've taken references or pointers to elements inside the vector, these still point to the old block, now dead memory, and is a serious bug! 如果您已经对向量中的元素进行了引用或指针,那么它们仍然指向旧块,现在是死记忆,并且是一个严重的错误!

So I'm guessing your particle effect keeps adding new particles to your particles vector, which at some point causes the vector to reallocate when it exceeds capacity. 所以我猜你的粒子效应会不断向你的粒子向量添加新的粒子,这在某些时候会导致向量在超出容量时重新分配。 The pointers stored by the Spring class aren't updated though, so point to dead memory and have no effect on the actual particle, which got moved somewhere else by the vector. Spring类存储的指针虽然没有更新,但是指向死记忆并且对实际粒子没有影响,实际粒子被矢量移动到其他地方。

Don't take a reference or pointer to an element inside a vector. 不要将引用或指针指向向量内的元素。 Use a vector of pointers, a list, or some other container which isn't going to shuffle around the memory addresses of actual elements. 使用指针,列表或其他容器的向量,它不会在实际元素的内存地址周围移动。 If you have to, use iterators to elements inside a vector. 如果必须,请使用迭代器到向量内的元素。 In debug builds, assuming you've got a checked STL implementation, you'll get a debug alert if you access the element through the iterator after the vector reallocates itself. 在调试版本中,假设您已经检查了STL实现,如果在向量重新分配自身后通过迭代器访问该元素,您将获得调试警报。

What you are doing looks OK - the following code creates a "2D" vector and illustrates that the .at().at() construct does give you a reference: 你正在做什么看起来没问题 - 下面的代码创建一个“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
}

I think this series from C++ FAQ Lite should help. 我认为C ++ FAQ Lite中的这个系列应该有所帮助。

Please don't be confused by "operator overloading" header. 请不要被“运算符重载”标题混淆。 You definitely should read 13.10, 13.11 and 13.12 from there. 你绝对应该从那里阅读13.10,13.11和13.12。

If I understand correctly you want to create a 2D array of Particles using std::vector ? 如果我理解正确你想使用std::vector创建一个粒子的2D数组?

If so you can declare it as: std::vector<std::vector<Particle> > . 如果是这样,您可以将其声明为: std::vector<std::vector<Particle> > You could then even use [][] nomenclature to access elements. 然后你甚至可以使用[][]命名法来访问元素。 ( Danger Will Robinson! No boundary checking while using this operator ) Danger Will Robinson!使用此运算符时无边界检查

However if this 2D array will contain mostly zeros then it might be ok to use a map with indices as keys. 但是,如果这个2D数组主要包含零,则可以使用带索引的map作为键。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM