Ссылка на элемент в 2-м векторе (C++)

У меня есть класс, названный 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-м векторе не становятся обновленными.

5
задан hrst 5 February 2010 в 13:36
поделиться

4 ответа

Одной из наиболее распространенных проблем, связанных с получением ссылок / указателей на элементы внутри векторов, является перераспределение. Если вы, например, push_back, возможно, вектор превысит свою емкость, выделит новый блок памяти, скопирует все заново, а затем освободит старый блок. Если вы взяли ссылки или указатели на элементы внутри вектора, они по-прежнему указывают на старый блок, теперь уже мертвую память, и это серьезная ошибка!

Итак, я предполагаю, что эффект вашей частицы продолжает добавлять новые частицы к вашему вектору частиц, что в какой-то момент заставляет вектор перераспределяться, когда он превышает емкость. Указатели, хранящиеся в классе Spring, не обновляются, поэтому указывают на мертвую память и не влияют на фактическую частицу, которая была перемещена вектором в другое место.

Не используйте ссылку или указатель на элемент внутри вектора. Используйте вектор указателей, список или какой-либо другой контейнер, который не будет перемещаться по адресам памяти фактических элементов. Если необходимо, используйте итераторы для элементов внутри вектора. В отладочных сборках, если у вас есть проверенная реализация STL, вы получите предупреждение об отладке, если вы получите доступ к элементу через итератор после того, как вектор перераспределится.

6
ответ дан 13 December 2019 в 05:34
поделиться

Если я правильно понимаю, вы хотите создать двумерный массив частиц, используя std :: vector ?

Если да, то можете объявите его как: std :: vector > . Тогда вы даже можете использовать номенклатуру [][] для доступа к элементам. ( Опасно, будет Робинсон! Никакой проверки границ при использовании этого оператора )

Однако, если этот 2D-массив будет содержать в основном нули, тогда было бы нормально использовать карту с индексами в качестве ключей.

0
ответ дан 13 December 2019 в 05:34
поделиться

То, что вы делаете, выглядит нормально - следующий код создает "двумерный" вектор и иллюстрирует, что конструкция .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
}
5
ответ дан 13 December 2019 в 05:34
поделиться

Думаю, эта серия из C++ FAQ Lite должна помочь.

Пожалуйста, не путайтесь в заголовке "Перегрузка операторов". Вам определенно стоит прочитать 13.10, 13.11 и 13.12 оттуда.

1
ответ дан 13 December 2019 в 05:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: