Пока объект остается в памяти и вы всегда ссылаетесь на один и тот же экземпляр (например, вы не передаете его по значению, а затем сравниваете этот объект с оригинальной или другой кэшированной копией), адрес всегда будет оставаться прежним и указатель является разумным идентификатором. Это очевидно верно - если объект перемещается в памяти, указатель больше не будет работать, и стандарт гарантирует, что указатели на разные объекты сравниваются с разными значениями. [Вот почему у вас не может быть объектов нулевой длины, поэтому следующий объект в памяти имеет другой адрес.]
Однако, если объект когда-либо будет передан по сети или сохранен на диск, очевидно, что это больше не будет работать, и вам придется сравнивать объект поэлементно или включать уникальный объект. значение идентификатора (он же первичный ключ).
ETA: ужасно правильно, что если вы перераспределите память, содержащую объекты, значения будут другими, но очевидно, что указатели не будут действительны вообще, поэтому ваша программа будет повреждена, если вы ожидаете, что указатели будут уникальными или нет. (И наоборот, если вы используете умные точки, которые будут отслеживать реакционные локаторы - по сути, как работают C # и .NET - значение не обязательно будет одинаковым, но значения указателей все равно будут разными в разных экземплярах объекта.) На самом деле, это правило - пока указатели действительны, вы должны иметь возможность сравнивать их, но вы не можете кешировать значение и ожидать, что оно будет работать какое-то неопределенное время спустя (в случае, если вы сначала уничтожите объект ), поэтому, если вы уверены, что этого не произойдет, это нормально, но имейте это в виду, часто вам захочется сериализовать объекты в какой-то момент, и тогда лучше спроектировать их с самого начала.