Как использовать алгоритм поиска с вектором указателей на объекты в c ++? - PullRequest
17 голосов
/ 03 ноября 2008

Я хочу найти в векторе указатели объектов для соответствующего объекта. Вот пример кода, иллюстрирующий мою проблему:

class A {
public:
    A(string a):_a(a) {}
    bool operator==(const A& p) {
        return p._a == _a; 
    }

private: 
    string _a;
};

vector<A*> va;

va.push_back(new A("one"));
va.push_back(new A("two"));
va.push_back(new A("three"));

find(va.begin(), va.end(), new A("two"));

Я хочу найти второй элемент, помещенный в вектор. Но поскольку vector определен как коллекция указателей, C ++ не использует мой перегруженный оператор, а использует неявное сравнение указателей. Каков предпочтительный C ++ - способ решения в этой ситуации?

Ответы [ 4 ]

17 голосов
/ 03 ноября 2008

Используйте find_if с функтором:

template <typename T>
struct pointer_values_equal
{
    const T* to_find;

    bool operator()(const T* other) const
    {
        return *to_find == *other;
    }
};


// usage:
void test(const vector<A*>& va)
{
    A* to_find = new A("two");
    pointer_values_equal<A> eq = { to_find };
    find_if(va.begin(), va.end(), eq);
    // don't forget to delete A!
}

Примечание: ваш оператор == для A должен быть константным или, что еще лучше, написать его как функцию, не являющуюся другом.

4 голосов
/ 03 ноября 2008

Либо используйте std :: find_if и предоставьте подходящий предикат самостоятельно, см. Другие ответы для примера этого.

Или, в качестве альтернативы, взгляните на boost :: ptr_vector , который обеспечивает прозрачный ссылочный доступ к элементам, которые действительно хранятся в виде указателей (в качестве дополнительного бонуса управление памятью также выполняется для вас)

1 голос
/ 04 ноября 2008

Вы также можете использовать Boost :: Lambda:

using namespace boost::lambda;
find_if(va.begin(), va.end(), *_1 == A("two"));

Конечно, вы должны предпочесть использовать shared_ptrs, чтобы не забыть удалить!

1 голос
/ 03 ноября 2008

Попробуйте вместо этого использовать find_if. У него есть параметр для предиката, где вы можете точно решить, как проверить, нашел ли вы нужный элемент.

http://www.sgi.com/tech/stl/find_if.html

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