Не должны ли функции operator [] и insert () вести себя одинаково на карте C ++?

0

Когда я использую оператор [] для вставки элементов на карту c++, возникает ошибка.

У меня есть эта переменная <Pair, int>. Когда я вставляю в него новый элемент, а затем использую итератор для печати его ключей, некоторые элементы карты случайно исчезают, а значения не печатаются в порядке возрастания. Однако, когда я вставляю элементы, используя funtion insert(), все работает нормально. Что я делаю неправильно с оператором []? Разве результат не должен быть одинаковым в обоих случаях?

Замечание: каждая пара ключей представляет собой структуру, хранящую пару целых чисел.

Вот пример: я вставляю шесть следующих ключей (5,9), (5,11), (5,12), (4,14), (1,10), (3,10). Затем я перебираю по карте и ключ (3,10) исчезает. Кроме того, элементы не печатаются по порядку. Чтобы увидеть правильный способ печати, просто следуйте инструкциям, приведенным в комментариях к коду ниже.

Вот мой код:

#include <iostream>
#include <map>

using namespace std;

struct Pair {
    int a;
    int b;

    Pair(const int& a,const int& b) { //assures the first int is the smaller one
        if (a < b) {
            this->a = a;
            this->b = b;
        } else {
            this->b = a;
            this->a = b;
        }
    }

    bool operator<(const Pair& otherPair) const {
        return this->a < otherPair.a || this->b < otherPair.b;
    }
};

int main() {
    Pair elements []{ Pair (5,9), Pair (5,11), Pair (5,12), Pair (4,14), Pair (1,10), Pair (3,10) }; // keys to insert into the map

    map<Pair,int> mapPairInt; // map to store the elements

    for(int i = 0; i <6;i++){ 
        mapPairInt[elements[i]] = 0; //insert elements using operator[]
        //mapPairInt.insert ( std::pair<Pair,int>(elements[i],0) ); // insert elements using insert() -- uncomment this line and comment the line above. This will make everything works properly
}

    //print the keys stored by the map (the keys should be printed in increasing order)
    map<Pair,int>::iterator it = mapPairInt.begin();
    while(it != mapPairInt.end()){
        cout<< it->first.a << "-" << it->first.b <<endl;
        it++;
    }

   return 0;
}
Теги:
struct
iterator
insert
map

2 ответа

5
Лучший ответ

Ваша Pair::operator<() нарушает требования std::map, а именно транзитивность. Например, (5,12) < (4,14) но в то же время (4,14) < (5,12). Это должно означать (5,12) < (5,12) что является ложным (и даже если бы оно было правдой, оно нарушало бы еще одно требование, нерефлексивность).

Это нарушение вызывает неопределенное поведение, поэтому все может случиться.

Кстати, самый компактный способ написания корректного оператора сравнения, который мне известен

bool operator< (const Pair& otherPair) const {
    return std::tie(a, b) < std::tie(otherPair.a, otherPair.b);
}
0
bool operator<(const Pair& otherPair) const {
    if (this->a == otherPair.a)
    {
        return this->b < otherPair.b;
    }
    return this->a < otherPair.a;
}

Это должен выглядеть ваш компаратор. Он дает ожидаемые результаты.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню