При использовании std:: map должен ли я перегрузить operator== для типа ключа?
у std::map не должно быть дублированных ключей, так как он знает, что у меня есть дублированный ключ, когда у меня есть пользовательский тип, мне нужно сделать перегрузку перегрузка operator==? Или он будет неявно создан?
согласно документации мне нужен только оператор
Рассмотрим пример:
class MyType{
public:
MyType(int newId){
id = new int;
*id = newId;
};
~MyType{
delete id;
}
private:
int* id;
};
int main(){
std::map<MyType,int> myMap;
std::pair<std::map<MyType,int>::iterator,bool> ret;
ret = myMap.insert ( std::pair<MyType,int>(myType(2),100) );
if (!ret.second) {//now how can he knows that?
std::cout << "element already existed" << endl;
}
}
4 ответов
std::map
не заботится о буквальном уникальность ключи. Он заботится о ключах эквивалентности. Ключи!--1--> и b
эквивалентны по определению, когда ни a < b
, ни b < a
- это правда.
обратите внимание также, что std::map
напрямую не использует operator <
. std::map
ничего не знает о operator <
. Вместо std::map
использует предикат сравнения, тип которого указан в качестве третьего параметра std::map
шаблон. Неисполнение значение этого параметра -std::less
. Реализация std::less
делегирует сравнение с operator <
(если не специализировано по-разному). Вот как!--6--> вступает в игру. Но вы всегда можете предоставить тур собственный предикат, который не обязательно будет использовать operator <
.
но в любом случае ключевым моментом здесь является то, что std::map
использует сравнение заказа " меньше "и только сравнение" меньше". Он не нуждается и не заботится о каких-либо сравнениях "равенства".
между тем, std::unordered_map
была бы другая история. Он опирается на неупорядоченное сравнение "равенства", указанное предикатом. По умолчанию это std::equal_to
. Реализация std::equal_to
делегирует вызов operator ==
(если специализировано по-разному).
вы должны перегрузить operator<
.
на std::map
будет сравнивать ключи с помощью
!(a < b) && !(b < a)
как тест на уникальность.
ассоциативные контейнеры order используют только строгий слабый порядок для идентификации ключей. Они не будут использовать operator==()
. Единственное сравнение, используемое для поиска объектов, - это третий аргумент шаблона std::map<K, V, Compare, Allocator>
.
сравнение используется для группировки ключей в наборы эквивалентности. Два ключа k1
и k2
считаются эквивалентными, если ни k1
меньше, чем k2
, ни k2
меньше, чем k1
:
bool equivalent = !(k1 < k2) && !(k2 < k1);
конечно, ассоциативный контейнеры фактически будут использовать что-то вроде
!predicate(k1, k2) && !predicate(k2, k1)