Определение, находится ли объект в std :: set - PullRequest
3 голосов
/ 04 мая 2009

Я пытаюсь определить, содержится ли объект внутри std::set. Согласно msdn (и другим источникам) функция set :: find должна возвращать end(), если не найдет запрошенный вами элемент.

Однако, когда я реализую код, подобный следующему, set::find возвращает вместо этого мусор (0xbaadf00d).

set<Cell*> cellSet;

Cell* cell = new Cell();    

if (cellSet.find(cell) == cellSet.end())
{
    ...
}

Я правильно использую это? Я работаю в Visual C ++ 2005.

Ответы [ 5 ]

10 голосов
/ 04 мая 2009

Ваш опубликованный код всегда будет выполнять код в пределах if, а 0xbaadf00d - это маркера реализации "один за другим".

5 голосов
/ 04 мая 2009

При использовании stl set мне нравится использовать функцию count для определения членства. Я думаю, что это облегчает чтение кода.

set<Cell*> cellSet;

Cell* cell = new Cell();    

if (cellSet.count(cell) == 0)
{
    ...
}
1 голос
/ 04 мая 2009

Имеет ли callSet.end () значение 0xbaadf00d?

EDIT

Я запустил этот пример кода в VS2008, и все заработало как положено. Функция find возвращает итератор, указывающий на исходное значение.

Какое поведение вы точно видите? Возвращает ли он end () или возвращает другое место в наборе?

0 голосов
/ 04 мая 2009

Одной простой ошибкой является то, что вы должны проверять, что не равно концу.

set<Cell*> cellSet;
Cell* cell = new Cell();
if (cellSet.find(cell) != cellSet.end())     // Test NOT EQUAL to end
{
     // Found item in set.
}

Но также следует помнить, что вы сравниваете не фактические значения ячейки, а указатель на объекты ячейки (которые могут быть, а могут и не совпадать с вашими). Обычно в C ++ вы не склонны хранить указатели в контейнерах, так как нет подразумеваемого владения указателем, но иногда это нормально.

Для фактического сравнения объектов вам нужно использовать find_if () и передать предикат (функтор).

struct PointerCellTest
{
    Cell&  m_lhs;
    PointerCellTest(Cell* lhs): m_lhs(lhs) {}
    bool operator()(Cell* rhs)
    {
         return lhs.<PLOP> == rhs.<PLOP>
    }
};


if(find_if(cellSet.begin(),cellSet.end(),PointerCellTest(cell)) != cellSet.end())
{
     // Found item in set.
}
0 голосов
/ 04 мая 2009

Попробуйте скомпилировать и запустить просто предоставленный вами фрагмент кода, и я гарантирую, что вы найдете, что он выполняется без проблем. Проблема почти наверняка связана с ошибками выделения памяти, возникающими в других местах вашей программы, такими как ссылка на неинициализированный указатель или указатель на объект, который был delete d.

Вам знакомо, как контейнеры C ++ управляют своими объектами? Они не удаляют указатели для вас. Всегда безопаснее использовать контейнеры объектов, а не указатели на объекты, когда это возможно. (Существуют случаи, когда необходимы контейнеры указателей, в частности, когда вы хотите, чтобы контейнер сохранял объекты разных типов из единой иерархии классов.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...