С++: реализация равного метода - как убедиться, что данный объект не является тем же самым ссылкой, что и этот?

Рассмотрим следующий фрагмент кода:

bool SomeObject::equal(const SomeObject& rhs) const
{
  if (this == &rhs)
  {
    return true;
  }

  // check the state
}

Проблема с этим кодом заключается в том, что SomeObject может переопределить operator& (или кто-то может добавить его в будущем), что, в свою очередь, может нарушить эту реализацию.

Можно ли проверить, являются ли теги rhs и *this одним и тем же объектом, не находясь во власти реализации operator&?

Ответ 1

Если вы хотите получить фактический адрес объекта и игнорировать перегруженные операторы &, используйте std::addressof

bool SomeObject::equal(const SomeObject& rhs) const
{
  if (this == std::addressof(rhs))
  {
    return true;
  }

  // check the state
}

Ссылка: http://en.cppreference.com/w/cpp/memory/addressof

Ответ 2

В С++ 11 есть функция std::addressof, которая должна делать то, что вы хотите.

Если вы хотите реализовать его самостоятельно, вы можете использовать кастинг для другого типа:

(SomeClass*)&reinterpret_cast<char&>(rhs)

Однако я бы не стал беспокоиться; Функция const equals должна работать нормально для идентичных параметров.

Ответ 3

Что делать, если вы просто полностью исключили это условие? Как часто кто-то собирается сравнивать объект с собой? Если вам, как правило, вообще нужно проверять все данные, то это простое сравнение просто тратит время в среднем случае. Пока ничего плохого не происходит, когда два объекта физически одинаковы (и ваша функция const, так что вы должны быть в порядке), то какой вред при выполнении небольшой дополнительной работы в редком случае?

Ответ 4

Просто передайте указатель на SomeObject вместо ссылки, так что вам больше не нужен оператор и.

Тогда он хотел бы:

bool SomeObject::equal(const SomeObject* rhs) const
{
    if ( this == rhs )
    {
         return true;
    }
    //...
}