Сценарий
У меня есть класс, который я хочу сравнить с равенством. Класс большой (он содержит растровое изображение), и я буду сравнивать его несколько раз, поэтому для эффективности я собираю данные и выполняю полную проверку равенства, если хэши совпадают. Кроме того, я буду сравнивать только небольшое подмножество своих объектов, поэтому я только вычисляю хэш при первой проверке равенства, затем используя сохраненное значение для последующих вызовов.
Пример
class Foo
{
public:
Foo(int data) : fooData(data), notHashed(true) {}
private:
void calculateHash()
{
hash = 0; // Replace with hashing algorithm
notHashed = false;
}
int getHash()
{
if (notHashed) calculateHash();
return hash;
}
inline friend bool operator==(Foo& lhs, Foo& rhs)
{
if (lhs.getHash() == rhs.getHash())
{
return (lhs.fooData == rhs.fooData);
}
else return false;
}
int fooData;
int hash;
bool notHashed;
};
Фон
В соответствии с руководством по этому ответу каноническая форма оператора равенства:
inline bool operator==(const X& lhs, const X& rhs);
Кроме того, приведен следующий общий совет для перегрузки оператора :
Всегда придерживайтесь операторов хорошо известной семантики.
Вопросы
-
Моя функция должна иметь возможность мутировать его операнды, чтобы выполнить хеширование, поэтому мне пришлось сделать их не
const
. Существуют ли какие-либо потенциальные негативные последствия этого (примерами могут быть стандартные библиотечные функции или контейнеры STL, которые ожидают, чтоoperator==
имеет операндыconst
)? -
Если мутирующая функция
operator==
считается противоречащей ее хорошо известной семантике, если мутация не имеет каких-либо наблюдаемых эффектов (потому что у пользователя нет возможности видеть содержимое хэша)? -
Если ответ на любой из вышеперечисленных вопросов - "да", то какой будет более подходящий подход?