2008-11-03 3 views
17

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

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")); 

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

ответ

17

Использование 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! 
} 

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

+0

Я думаю, это должно быть find_if в коде? – esrkan 2008-11-03 15:21:52

1

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

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

4

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

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

1

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

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

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