Определение того, находится ли объект в std::set
Вопрос
Я пытаюсь определить, содержится ли объект уже в 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.
Решение
Ваш опубликованный код всегда будет выполнять код внутри if
, а 0xbaadf00d
равно «реализации одного шага» конец & Quot; маркер.
Другие советы
При использовании stl set мне нравится использовать функцию count для определения членства. Я думаю, что это облегчает чтение кода.
set<Cell*> cellSet;
Cell* cell = new Cell();
if (cellSet.count(cell) == 0)
{
...
}
Имеет ли callSet.end() также значение 0xbaadf00d?
Редактировать
Я запустил этот пример кода в VS2008, и все сработало, как ожидалось.Функция find вернула итератор, указывающий на исходное значение.
Какое именно поведение вы наблюдаете?Возвращает ли он end() или возвращает другое место в наборе?
Попробуйте скомпилировать и запустить просто предоставленный вами фрагмент кода, и я гарантирую, что вы обнаружите, что он выполняется без проблем. Эта проблема почти наверняка связана с ошибками выделения памяти, возникающими в других местах вашей программы, такими как ссылка на неинициализированный указатель или указатель на объект, который был delete
d.
Вы знакомы с тем, как контейнеры C ++ управляют своими объектами? Они не удаляют указатели для вас. Всегда безопаснее использовать контейнеры объектов, а не указатели на объекты, когда это возможно. (Существуют случаи, когда необходимы контейнеры указателей, в частности, когда вы хотите, чтобы контейнер сохранял объекты разных типов из единой иерархии классов.)
Одна простая ошибка заключается в том, что вы должны проверять, чтобы не было конца.
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.
}