У меня есть класс, названный Spring в системе частиц. Конструктор похож:
Spring(Particle& _a, Particle& _b);
И у меня есть вектор Частиц, и я использую
Spring mySpring = Spring(myParticles.at(j),myParticles.at(j+1));
в цикле для добавления усилия пружины между двумя частицами. Все хорошо работает до сих пор. Однако я хочу использовать 2-й вектор Частиц. Это:
Spring mySpring = Spring(myParticles.at(i).at(j),myParticles.at(i).at(j+1));
И я не получаю ссылку на частицу. В первом примере, каждый раз, когда я изменяю частицу в своем пружинном классе, изменяется частица в векторе. Во втором примере изменения только локально. Как я могу изменить частицы в 2D Векторе?
Править: Я пытаюсь ясно дать понять некоторые вещи:
У меня есть некоторые системы частиц, и каждый из них состоит из многих частиц. Каждая частица должна только взаимодействовать с другими частицами, которые находятся в той же системе как самой. Поэтому у меня есть вектор систем частиц с каждой системой частицы, являющейся вектором объектов частицы. (Который делает 2-й вектор). Первый размер (i) является системой, второе (j) отдельная частица. Частицы в системе взаимодействуют друг с другом (столкнитесь, избегайте, безотносительно..) и их изменение положений. И вектор "обновляется". (Таким образом, ссылочные работы).
Однако у меня есть секунда (1d) вектор усилий пружины. Усилие пружины также используется для обновления положений частиц. Мой конструктор делает следующее:
Spring::Spring(Particle& _a, Particle& _b) {
a=&_a;
b=&_b; }
С a и b быть Particle*. Таким образом, я храню указатели на две частицы в 2-м векторе. Другой функциональный Spring.doSpring () меняет положения частиц.
a->pos.x=300;
или
a->velocity+=something..
В первом примере, который я отправил, я использовал только одну систему частиц и таким образом, не было никакой потребности в 2-м векторе. И все хорошо работает. Частицы в векторе обновляются. Но со вторым примером мои прогоны программы, но так или иначе независимо от того, что делает функция doSpring, частицы в 2-м векторе не становятся обновленными.
Одной из наиболее распространенных проблем, связанных с получением ссылок / указателей на элементы внутри векторов, является перераспределение. Если вы, например, push_back, возможно, вектор превысит свою емкость, выделит новый блок памяти, скопирует все заново, а затем освободит старый блок. Если вы взяли ссылки или указатели на элементы внутри вектора, они по-прежнему указывают на старый блок, теперь уже мертвую память, и это серьезная ошибка!
Итак, я предполагаю, что эффект вашей частицы продолжает добавлять новые частицы к вашему вектору частиц, что в какой-то момент заставляет вектор перераспределяться, когда он превышает емкость. Указатели, хранящиеся в классе Spring, не обновляются, поэтому указывают на мертвую память и не влияют на фактическую частицу, которая была перемещена вектором в другое место.
Не используйте ссылку или указатель на элемент внутри вектора. Используйте вектор указателей, список или какой-либо другой контейнер, который не будет перемещаться по адресам памяти фактических элементов. Если необходимо, используйте итераторы для элементов внутри вектора. В отладочных сборках, если у вас есть проверенная реализация STL, вы получите предупреждение об отладке, если вы получите доступ к элементу через итератор после того, как вектор перераспределится.
Если я правильно понимаю, вы хотите создать двумерный массив частиц, используя std :: vector
?
Если да, то можете объявите его как: std :: vector
. Тогда вы даже можете использовать номенклатуру [][]
для доступа к элементам.
( Опасно, будет Робинсон! Никакой проверки границ при использовании этого оператора )
Однако, если этот 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
}
Думаю, эта серия из C++ FAQ Lite должна помочь.
Пожалуйста, не путайтесь в заголовке "Перегрузка операторов". Вам определенно стоит прочитать 13.10, 13.11 и 13.12 оттуда.