Лучшая практика: как получить уникальный идентификатор объекта
У меня есть несколько объектов и вам нужно создать для них уникальный идентификатор, который не будет изменен/повторен в течение всего жизненного цикла каждого объекта.
В принципе, я хочу получить/создать уникальный идентификатор для моих объектов, smth вроде этого
int id = reinterpret_cast<int>(&obj);
или
int id = (int)&obj;
Я понимаю, что коды выше - это плохие идеи, поскольку int может быть недостаточно большим для хранения адреса и т.д.
Итак, какова наилучшая практика получения уникального идентификатора от объекта, который будет переносным решением?
Ответы
Ответ 1
В зависимости от ваших требований "уникальности" существует несколько вариантов:
- Если уникальное внутри одного адресного пространства ( "в рамках выполнения одной программы" ) ОК , а ваши объекты остаются там, где они находятся в памяти, то указатели в порядке. Однако есть подводные камни: если ваши объекты живут в контейнерах, каждое перераспределение может изменить идентификатор ваших объектов, и если вы разрешите копирование своих объектов, тогда объекты, возвращенные из какой-либо функции, могут быть созданы по тому же адресу.
- Если вам нужна более глобальная уникальность, например, потому что вы имеете дело с коммуникационными программами или постоянными данными, используйте GUID/UUIds, такие как boost. UUID.
- Вы можете создавать уникальные целые числа из некоторого статического счетчика, но остерегайтесь ловушек:
- Убедитесь, что ваши приращения являются атомарными
- Защитите от копирования или создания собственных конструкторов копий, операторов присваивания.
Лично мой выбор был UUID, когда я могу их себе позволить, потому что они дают мне некоторую легкость ума, не имея необходимости думать обо всех ловушках.
Ответ 2
Если объекты должны быть однозначно идентифицированы, вы можете сгенерировать уникальный идентификатор в конструкторе:
struct Obj
{
int _id;
Obj() { static int id = 0; _id = id++; }
};
Вам нужно будет решить, как вы хотите обрабатывать копии/назначения (тот же идентификатор - выше будет работать/другой идентификатор), вам понадобится конструктор копирования и, возможно, член класса static
вместо static
локальная переменная).
Ответ 3
Когда я просмотрел эту проблему, я довольно быстро оказался в библиотеке Boost UUID (универсально уникальный идентификатор http://www.boost.org/doc/libs/1_52_0/libs/uuid/). Однако по мере роста моего проекта я перешел к библиотеке Qt GUID (глобальный уникальный идентификатор http://doc.qt.digia.com/qt/quuid.html).
Урок, извлеченный для меня, состоял в том, чтобы начать объявление своего собственного класса UUID и скрыть реализацию, чтобы вы могли переключиться на все, что вы найдете позже.
Я надеюсь, что это поможет.
Ответ 4
Если ваш объект является классом, тогда у вас может быть статическая переменная-член, которой вы являетесь intestinal равным 0. Затем в конструкторе вы храните это значение в экземпляре класса и увеличиваете статическую переменную:
class
Indexed
{
public:
Indexed() :
m_myIndex( m_nextIndex++ )
{ }
int getIndex() const
{ return m_myIndex; }
private:
const int m_myIndex;
static int m_nextIndex;
};
Ответ 5
Это не похоже на плохую идею использовать адрес объекта как уникальный (для этого прогона) идентификатор, напрямую. Зачем бросать его в целое число? Просто сравните указатели с ==
:
MyObject *obj1, *obj2;
...
if (obj1 == obj2) ...
Это не сработает, конечно, если вам нужно писать идентификаторы в базу данных или тому подобное. Те же самые значения для указателей возможны между прогонами. Кроме того, не перегружайте оператор сравнения (==
).
Ответ 6
Если вам нужен уникальный идентификатор для распределенной среды, используйте boost:: uuid