хранение ссылки / указателя на объект std :: set

Я делаю игру о мраморе, которая использует структуру для описания свойств мрамора:

struct Marble
{
Color color;
int weight;
//Other customizable marble properties
};

Я в настоящее время использую std::vector чтобы отслеживать, какие шарики находятся в какой позиции на игровом поле:

std::vector<Marble> m_marbles;

В любое время я могу проверить свойства мрамора с учетом его положения путем индексации по вектору. Чтобы проверить цвет мрамора в позиции 20:

m_marbles[20].color;

Пользователь может создавать собственные шарики и добавлять их на игровую доску. Если я хочу добавить новый мрамор на игровое поле, я создаю новый объект структуры и помещаю его в вектор:

Marble m;

//Fill struct with marble information

m_marbles.push_back(m)

Проблема в том, что игровое поле очень большое (много тысяч шариков), и многие шарики точно такие же.

Допустим, на игровой доске 4000 позиций. Возможно, 3000 из них — красный мрамор весом 1,0. В текущем решении 3000 эквивалентных объектов Marble занимают место в моем векторе.

Поскольку пользователь может определять свои собственные типы мрамора, я не могу просто жестко закодировать все возможные типы мрамора, а затем заставить вектор хранить указатель на соответствующий мраморный объект.

Я думал об использовании std::set хранить разные виды мрамора. Затем, когда пользователь отправляется на создание своего собственного мрамора, он может попытаться вставить его в набор. Если такой же тип мрамора уже существует, он не будет тратить память.

У меня вопрос, как я могу сохранить ссылку в std::set? Например, скажем, мой набор состоит из следующих типов мрамора:

{RedMarble, BlueMarble, StrangeMarble, ConfusedMarble}

Теперь я хочу назначить красный мрамор на позицию 20 на игровом поле:

m_marbles[20] = ?

Я также хочу проверить цвет мрамора в позиции 31:

m_marble[31].color;

Можно ли так работать с набором? Функции поиска и вставки возвращают итераторы, но не станут ли они недействительными, если я добавлю больше элементов в набор?

1

Решение

Да, вы можете делать то, что вы пытаетесь сделать. Вы можете хранить указатели в своем векторе, которые указывают на шарики в вашем наборе. Или вы можете хранить итераторы в вашем векторе, опять же, какие итераторы указывают на Marbles в вашем наборе.

Вот как я бы сделал это с помощью указателей:

// A useful helper funtction -- not required, but useful.
const Marble* Helper(const Marble& m) {
static std::set<Marble> uniqueMarbles;
return &*(uniqueMarbles.insert(m).first);
}

// A vector of pointers to marbles
std::vector<const Marble*> m_marbles;

// You can pass temporaries to the helper function, and it returns a permanent pointer
m_marbles.push_back(Helper(Marble(RED, 1.0));

Marble m;
m.setColor(BLUE);
m_marbles.push_back(Helper(m));// You can reference your marbles
Color c = m_marbles[i]->getColor();

// Hopefully the following will produce a compiler error message
m_marbles[i]->setColor(GREEN); // Oops, m_marbles holds const pointers
0

Другие решения

Вы должны сделать вектор содержать указатели Мраморные конструкции:

std::vector<Marble*> m_marbles;

Указатель не занимает много места, и вы все еще можете использовать Marble в качестве базового класса.

0

Если игровая доска на самом деле всего несколько тысяч мест, я бы не стал тратить время впустую. Например

10000 places * sizeof(Marble) = 10000 * 100 bytes ~ 1 MB

Не большой объем памяти по сегодняшним меркам.

Если он может стать очень большим, то вы действительно можете хранить свои уникальные шарики в наборе и ссылаться на них с помощью указателя, как уже показывал @BenRuijl.

0

Построить класс Marble содержащий указатель на MarbleType определение свойств каждого мрамора (для каждого вида мрамора у вас есть один экземпляр MarbleType). Вектор может содержать Marbles или общие указатели на Marbleс или уникальные указатели. Если Marble класс невелик (образец в навесном весе), вы не теряете места, но тем не менее имеете чистое и гибкое решение. Типы мрамора могут быть названы (например, строкой) и храниться в std::map,

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector