std::map::size() отличается от итераторов

Я использую std::map с пользовательским классом сравнения и пользовательскими классами в качестве ключа.

Теперь я использую оператор [] для доступа к элементам по ключу. Однако это, похоже, создает большую проблему. Кажется, что карта неправильно распределяет элементы или они повреждены. Это становится очевидным, потому что мой пользовательский класс сравнения генерирует исключение, когда обнаруживает, что один из сравниваемых объектов имеет произвольные значения, хранящиеся в его полях данных (что, по-видимому, подразумевает, что конструктор не запускался или что объект никогда не создавался в первое место)

Теперь обнаруживается еще одно несоответствие:

Когда я вызываю std::map::size() и сравниваю его с тем, сколько раз я могу увеличить итератор begin(), чтобы добраться до итератора end(), тогда они не совпадают.

В частности, карта сообщает о большем size(), чем она, по-видимому, содержит.

Класс, который я использую в качестве ключа, представляет собой пользовательский матричный класс с полями данных:

unsigned int
unsigned int
vector<vector<Another Class>>

Однако ни в одном из этих классов я не использую арифметику указателей или что-то еще, что могло бы напрямую манипулировать памятью. Также у меня нет настраиваемых конструкторов копирования ни в одном из используемых классов.

РЕДАКТИРОВАТЬ: функция сравнения

struct SymModMatComp
{
  bool operator()(const ModMat& mat1, const ModMat& mat2) const
  {
    unsigned int rows = mat1.get_row_number();

    unsigned int columns = mat1.get_column_number();
    if(mat2.get_row_number() != rows || mat2.get_column_number() != columns)
    {
      throw dimension_mismatch();
    }
    for(unsigned int i = 0; i < rows; i++)
    {
      for(unsigned int j = 0; j < columns; j++)
      {
        if(mat1.get_item(i,j).get_value() < mat2.get_item(i,j).get_value())
        {
          return true;
        }
        else if(mat1.get_item(i,j).get_value() > mat2.get_item(i,j).get_value())
        {
          return false;
        }
      }
    }
    return false;
  }
}

get_value() возвращает беззнаковое целое число

РЕШЕНО:

Я использовал valgrind для проверки любых ошибок доступа к памяти... Я обнаружил, что совершенно не связанная часть программы, на самом деле, выполняла удаление уже удаленного объекта снова и снова....

Похоже, это испортило пространство, в котором хранились предметы на карте.

Но спасибо за все хорошие идеи!


person Blackclaws    schedule 29.10.2012    source источник
comment
Покажи нам свой код.   -  person Kiril Kirov    schedule 29.10.2012
comment
Кстати, странный ключ - целая матрица? И использование operator[] с целой матрицей... звучит ужасно медленно и кажется мне плохим дизайном (без обид).   -  person Kiril Kirov    schedule 29.10.2012
comment
В частности, вам нужно показать функцию сравнения; вполне вероятно, что он не производит строгого слабого упорядочения.   -  person ecatmur    schedule 29.10.2012
comment
@KirilKirov На самом деле это быстрее, чем можно подумать. И проблема в том, что единственная вещь, которая точно характеризует мои объекты, — это эта матрица, поэтому мне нужно сохранить ее как ключ.   -  person Blackclaws    schedule 29.10.2012
comment
Что возвращает get_value()? Это встроенный тип или пользовательский класс? SymModMatComp выглядит нормально, но, возможно, operator< для того, что возвращает get_value(), работает неправильно.   -  person Gorpik    schedule 29.10.2012


Ответы (2)


Без кода сложно догадаться, но я все равно попробую.

Знаете ли вы, что T& operator[] ( const key_type& x ); вставить значение в карту, если ключа там нет? Таким образом, размер карты увеличится на единицу, если у вас еще нет ключа на карте.

Элемент будет создан с использованием конструктора по умолчанию.

person Alessandro Teruzzi    schedule 29.10.2012

Если вы столкнулись с повреждением map со сложными определяемыми пользователем ключами, вероятно, ваша функция сравнения не соответствует требованиям строгий слабый порядок:

  • иррефлексивность: !(x < x)
  • асимметрия: !(x < y && y < x)
  • транзитивность: x < y && y < z -> x < z
  • транзитивность несравнимости: !(x < y || y < x || y < z || z < y) -> !(x < z || z < x)

Если какое-либо из этих требований не выполняется, результатом будет неопределенное поведение (например, повреждение памяти).

Если матрица участвует в функции сравнения, простой способ обеспечить строгое слабое упорядочение — использовать лексикографическое упорядочение ее элементов.

person ecatmur    schedule 29.10.2012