В следующем примере кода, потому что я сравниваю два std::map
объекты, я вынужден реализовать MyId::operator==()
,
MyId
это простой класс: в основном это обертка над массивом. Это заставило меня задуматься, почему оператор равенства обязателен: почему нам не дан битовый компаратор по умолчанию? В конце концов, нам дают оператор присваивания по умолчанию, который делает побитовое пошаговое копирование между объектами.
Я понимаю разницу между глубокими и мелкими копиями и необходимость для операторов присваивания и равенства. Мой вопрос: почему не существует «битовой проверки на равенство» по умолчанию, когда есть назначение по умолчанию?
#include <iostream>
#include <map>
#include <cstring>
typedef int myid[ 3 ];
struct MyId
{
myid id_;
bool operator<( const struct MyId& other ) const { return this < &other; }
bool operator==( const struct MyId& other ) const
{
return ( 0 == std::memcmp( id_, other.id_, sizeof( myid ) ));
}
};
int main( int argc, char* argv[] )
{
std::map< MyId, int> map;
MyId id = { 1, 2, 3 };
map[ id ] = 5;
std::map< MyId, int> map2;
map2[ id ] = 5;
// This forces implementation of MyId::operator==():
std::cout << std::boolalpha <<( map == map2 ) << std::endl;
MyId i1 = { 4, 5, 6 };
MyId i2 = { 7, 8, 9 };
// No required implementation of MyId::operator=():
i1 = i2;
return 0;
}
Обновить: Публично исправил мой пердящий мозг RE: побитовый или членский оператор присваивания по умолчанию.
В конце концов, нам дают оператор присваивания по умолчанию, который делает
побитовое копирование между объектами.
Нет, это не так. Напротив, заданный по умолчанию оператор копирования-назначения сконструирован таким образом, что он копирует-присваивает каждому члену объекта. В зависимости от того, как операторы копирования присваиваются в типах полей, результат может быть далек от побитовой копии.
В любом случае поведение по умолчанию при назначении копии (или при создании копии, или при перемещении, или даже уничтожении) разработано таким образом, чтобы соответствовать общим базовым потребностям. Основываясь на спецификации языка, он доступен в большинстве случаев, но существуют известные ситуации, когда язык не уверен в вашей семантике, и для него требуются четкие определения.
Оператор равенства отличается. Фактическое отношение равенства подразумевается не синтаксисом языка, а чисто семантикой. Компилятор не знает, как вы видите два экземпляра класса «равный» — поэтому он требует, чтобы вы сказали ему.
Других решений пока нет …