我在使用STL的时候遇到了一个速度突发,看起来像是一个正常的场景,简化了这里:
class Person {
string Name;
int Age;
};
vector<Person> people;
AddPeople(people);
string s("Bob");
find(people.begin(), people.end(), s);
find
想要比较整个班级。
有一些潜在的解决方法:
完全放弃find
(混乱,但可以重构):
bool bBob = false;
for (UINT i = 0; i < people.size(); i++) {
if (people[i].Name == s)
bBob = true;
break;
}
提供转换运算符(隐式转换不起作用;显式不能在find
中使用):
class Person {
string Name;
int Age;
operator string() {return Name;}
};
Person b ("Bob", 99);
string s ("Bob");
b == s; //doesn’t work
string(b) == s; //works, but no good for find()
定义一个独立的相等运算符(简单,有效,但全局公开):
BOOL operator==(Person l, string r) {
return l.Name == r;
}
定义成员相等运算符(使比较顺序依赖;对象必须是第一个):
class Person {
string Name;
int Age;
bool operator==(string s) {return Name == s;}
};
Person b ("Bob", 99);
string s ("Bob");
b==s; //works
s==b; //doesn’t work, but not a problem for find()
看起来#4是最好的候选人,但似乎没有理想或感觉“STL”,有些人有问题。
答案 0 :(得分:5)
有没有更好或更合适的方法来实现“STL方式”?
您可以使用std::find_if
(由C ++ 11 lambdas提供支持):
std::string name = "Bob";
// ...
std::find_if(std::begin(people), std::end(people),
[&] (Person const& p) { return p.Name == name; }
注意,称之为“STL方式”是不合适的。这是C ++标准库,而不是STL(“标准模板库”)。 STL是C ++标准库的容器和算法库的强大灵感,但两者并不相同。有关详细信息,请参阅this Q&A on StackOverflow。
修改强>
由于您使用的是不支持lambdas的编译器,因此您可以定义自己的仿函数谓词:
struct person_has_name
{
person_has_name(std::string const& n) : name(n) { }
bool operator () (Person const& p) { return p.Name == name; }
private:
std::string name;
};
以这种方式与std::find_if
一起使用:
std::string name = "Bob";
// ...
std::find_if(people.begin(), people.end(), person_has_name(name));
答案 1 :(得分:1)
有几种方法可以做到这一点,所有方法都涉及某种可调用对象和std::find_if
。
第一种是使用新的C ++ 11 lambda:
std::find_if(people.begin(), people.end(), [](const Person& person)
{ return person.Name == "Bob"; });
如果你有一个不支持lambdas的旧编译器,你可以使用functor object:
class FindPersonByName
{
std::string name;
public:
FindPersonByName(const std::string& name) : name(name) {}
bool operator()(const Person& person) const
{ return person.Name == name; }
};
std::find_if(people.begin(), people.end(), FindPersonByName("Bob"));
当然,这两个都要求您的班级公开Name
成员。但您可以将其更改为使用公共GetName
函数,并将其添加到类中。
答案 2 :(得分:1)
我想你想要这些用于子类或共享名为name的属性的类,如果不是,你可以自己创建一个简单的函数。如果您希望它适用于任何具有属性名称的类,您可以创建如下模板:
template < class ClassWithNameProperty >
ClassWithNameProperty * searchName (std::string name,
std::vector<ClassWithNameProperty *> array)
{
for (ClassWithNameProperty * obj: array)
{
if (obj.compare(obj->name))
{
return obj;
}
}
return NULL;
}
或者您希望搜索功能正常工作,希望这有助于您