C++ 从列表中删除STL
我在STl方面有问题。我正在尝试遍历学生对象的STL列表。当我找到匹配的比较时,我试图删除对象。但是,在进行比较时,我收到一个错误。这就是我到目前为止所做的:C++ 从列表中删除STL,c++,stl,iterator,C++,Stl,Iterator,我在STl方面有问题。我正在尝试遍历学生对象的STL列表。当我找到匹配的比较时,我试图删除对象。但是,在进行比较时,我收到一个错误。这就是我到目前为止所做的: string studentName; cout<<"Enter name of student to remove"; cin>>studentName; list<Student>::iterator
string studentName;
cout<<"Enter name of student to remove";
cin>>studentName;
list<Student>::iterator it = studentList.begin();
while (it != studentList.end()){
if(*it== studentName){
studentList.erase(it);
}
}
字符串studentName;
coutstudentName;
list::iterator it=studentList.begin();
while(it!=studentList.end()){
如果(*it==studentName){
学生名单。删除(它);
}
}
我得到错误“二进制表达式('value_type'(aka'Student')和'string'(aka'basic_string,allocator>')的操作数无效”
我不太清楚如何解决它。
谢谢,任何建议都将不胜感激 删除迭代器指向的列表段时,迭代器不再有效。这就是为什么
erase
将一个新的迭代器返回到被擦除的元素后面的元素。此外,您可能希望在循环中的某个点增加迭代器。试试这个:
while (it != studentList.end()){
if(*it == studentName)
it = studentList.erase(it);
else
++it;
}
编辑:现在您已经发布了错误,很明显您还有另一个问题。查看每个人关于如何修复此问题的答案。您的循环实际上相当于以下
for
循环:
for (list<Student>::iterator it = studentList.begin();
it != studentList.end();
/* EMPTY */)
{
if(*it== studentName){
studentList.erase(it);
}
}
但是此修复程序在另一方面存在缺陷。这是因为删除节点时,会在删除节点后跳过该节点,因此会错过一个节点。简单的解决方案是,如果不删除节点,则只增加it
:
while (it != studentList.end()){
if(*it== studentName){
studentList.erase(it);
} else {
++it; // Make iterator "point" to the next node
}
}
此解决方案的缺陷在于,如果删除节点,将具有未定义的行为。这是因为it
不会被更新,在循环的下一次迭代中,您将取消对不再存在的节点的迭代器的引用。这个问题的解决方案是知道什么,即对以下节点的迭代器。这意味着一个有效的解决方案看起来像
while (it != studentList.end()){
if(*it== studentName){
it = studentList.erase(it); // Make iterator "point" to node after removed node
} else {
++it; // Make iterator "point" to the next node
}
}
您正在将
Student
的实例与std::string
进行比较,我假设该字符串没有定义的运算符==
重载函数。您可以定义此运算符,也可以将studentName
与存储学生姓名的Student
中的成员字符串变量进行比较。您可以考虑在代码库中查看<代码> STD::ReaveVII:< /C> >,您可以使用它来过滤任何没有该名称的学生。 < P>您试图将学生与String进行比较。默认情况下未定义此类比较,因此您必须自己定义适当的运算符,或者编写类似于(*it).getName()==studentName
,其中getName是返回学生姓名的Student的成员函数。
此外,您的for循环不正确。应该是这样的:
for(auto it = studentList.begin(); it != studentList.end();) {
if((*it).getName() == studentName) {
it = studentList.erase(it);
} else {
++it;
}
}
bool operator==(const Student& student, const std::string& name) {
return student.name == name;
}
编辑:如果您决定重载比较运算符,则以下是有关如何操作的提示:
bool operator==(const Student& student, const std::string& name) {
return student.getName() == name;
}
bool operator==(const std::string& name, const Student& student) {
return student == name;
}
bool operator!=(const Student& student, const std::string& name) {
return !(student == name);
}
bool operator!=(const std::string& name, const Student& student) {
return !(student == name);
}
对于这个问题,上述四个重载中的第一个就足够了,但通常最好定义几个版本,以避免将来出现任何意外。此外,如果Student类没有任何像getName这样的成员函数(强烈建议使用这样的函数,除非Student是一个所有数据成员都是公共的简单结构),那么您必须更改第一个重载(其余的重载引用第一个重载,以便自动调整以适应更改),如下所示:
for(auto it = studentList.begin(); it != studentList.end();) {
if((*it).getName() == studentName) {
it = studentList.erase(it);
} else {
++it;
}
}
bool operator==(const Student& student, const std::string& name) {
return student.name == name;
}
此外,如果学生的姓名是私人的或受保护的,并且无法从公共上下文中访问,则您还必须在学生定义中添加朋友声明:
class Student {
public:
// Public interface...
private:
std::string name;
friend bool operator==(const Student& student, const std::string& name);
};
朋友声明的位置并不重要,只要它在类的定义中就行。同样,您只需要将第一个重载设置为特权,因为其余重载只调用第一个重载。现在可以更改循环:
for(auto it = studentList.begin(); it != studentList.end();) {
if(*it == studentName) {
it = studentList.erase(it);
} else {
++it;
}
}
您正在尝试比较字符串和学生。此外,您没有推进迭代器,因此循环将无法停止。试着做以下几点:
while (it != studentList.end()) {
if(it->getName == studentName) {
it = studentList.erase(it);
}
++it;
}
你忘记的事情:1。一个完整的代码示例。(例如,从未定义过studentList)2。编译器的实际错误。我修复了循环,但是如果(*it==studentName)您的解决方案工作正常,它会抛出一个错误!出于学习的目的,你能不能给我一些建议,告诉我如何重载==运算符,因为我使用的是迭代器。不管你是否使用迭代器。我编辑了答案,向您展示了如何重载运算符。最后一个for循环是错误的。如果循环找到一个等于
studentName
的对象,那么它将跳过下一个元素-它根本不会检查它。所以我会坚持最后一个解决方案。@navyblue我知道它出了问题,但很难找出答案。谢谢你提醒我。