Лучшая практика: как получить уникальный идентификатор объекта

У меня есть несколько объектов и вам нужно создать для них уникальный идентификатор, который не будет изменен/повторен в течение всего жизненного цикла каждого объекта.

В принципе, я хочу получить/создать уникальный идентификатор для моих объектов, 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