Ссылка на элемент в 2d векторе (c ++) - PullRequest
5 голосов
/ 05 февраля 2010

У меня есть класс с именем Spring в системе частиц. Конструктор выглядит так:

Spring(Particle& _a, Particle& _b);

И у меня есть вектор частиц, и я использую

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

внутри петли, чтобы добавить силу пружины между двумя частицами. Пока все отлично работает. Тем не менее, я хочу использовать 2d вектор частиц. То есть:

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

И я не получаю ссылку на частицу. В первом примере, когда я меняю частицу в своем классе пружины, частица в векторе меняется. Во втором примере изменения только локально. Как я могу изменить частицы в 2D векторе?

EDIT: Я пытаюсь прояснить некоторые вещи:

У меня есть несколько систем частиц, и каждая из них состоит из нескольких частиц. Каждая частица должна взаимодействовать только с другими частицами, которые находятся в той же системе, что и она сама. Поэтому у меня есть вектор систем частиц, где каждая система частиц является вектором объектов частиц. (Это делает 2d вектор). Первое измерение (i) - это система, второе (j) - отдельная частица. Частицы в системе взаимодействуют друг с другом (сталкиваются, избегают, что угодно ..), и их положения меняются. И вектор «обновляется». (То есть ссылка работает).

Однако у меня есть второй (1d) вектор сил пружины. Усилие пружины также используется для обновления положения частиц. Мой конструктор делает следующее:

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

А и В - это частица *. Так что я храню указатели на две частицы в 2-м векторе. Другая функция Spring.doSpring () изменяет положение частиц.

a->pos.x=300;

или

a->velocity+=something..

В первом примере, который я опубликовал, я использовал только одну систему частиц, и поэтому не было необходимости в двухмерном векторе. И все работает отлично. Частицы в векторе обновляются. Но во втором примере моя программа запускается, но каким-то образом, независимо от того, что делает функция doSpring, частицы в 2d-векторе не обновляются.

Ответы [ 4 ]

6 голосов
/ 05 февраля 2010

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

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

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

5 голосов
/ 05 февраля 2010

То, что вы делаете, выглядит нормально - следующий код создает «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
}
1 голос
/ 05 февраля 2010

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

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

0 голосов
/ 05 февраля 2010

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...