我不知道如何从列表中删除一个项目。
请注意,我想从advance()
函数中执行删除。这段代码只是从我的实际项目中提炼出来的,试图隔离错误。
#include <iostream>
#include <list>
#include <iterator>
#include <algorithm>
using namespace std;
const int SCT_OSC_FILLED = 11;
class OrderInfo {
private:
std::string id;
public:
OrderInfo(std::string a, int aStatusCode);
std::string key();
int statusCode;
};
OrderInfo::OrderInfo(std::string a, int aStatusCode) {
id = a;
statusCode = aStatusCode;
}
std::string OrderInfo::key() {
return id;
}
std::list <OrderInfo> MasterOrders;
void testList();
void add(OrderInfo ordInfo);
void advance(OrderInfo ordInfo, std::list <OrderInfo> ::iterator& orderIter);
void testList() {
OrderInfo o1("1", 15);
OrderInfo o2("2", 16);
OrderInfo o3("3", SCT_OSC_FILLED);
OrderInfo o4("4", 17);
OrderInfo o5("5", SCT_OSC_FILLED);
OrderInfo o6("6", 18);
add(o1);
add(o1);
add(o2);
add(o3);
add(o4);
add(o5);
add(o6);
for (auto v : MasterOrders)
std::cout << v.key() << "n";
}
void add(OrderInfo ordInfo) {
// Add to MasterOrders (if not already in list)
bool alreadyInList = false;
std::list <OrderInfo> ::iterator orderIter = MasterOrders.begin();
while (orderIter != MasterOrders.end())
{
OrderInfo oi = *orderIter;
alreadyInList = ordInfo.key() == oi.key();
if (alreadyInList) break;
advance(ordInfo, orderIter);
}
if (!alreadyInList) MasterOrders.push_front(ordInfo);
}
void advance(OrderInfo ordInfo, std::list <OrderInfo> ::iterator& orderIter) {
bool iterate = true;
if (ordInfo.statusCode == SCT_OSC_FILLED) {
orderIter = MasterOrders.erase(orderIter++); // https://stackoverflow.com/a/5265561/270143
iterate = false;
}
if (iterate) orderIter++;
}
int main()
{
testList();
return 0;
}
更新:我忘了说明实际的目标
我的目标是从advance()
方法中删除SCT_OSC_FILLED
ordInfo
s(那部分很重要),剩下的就别管了。我实际的项目代码所做的比所显示的要多,这些函数的名称只是为了这个例子而组成的。在我的实际项目中,有更多的代码与操纵列表没有直接关系(但与处理OrderInfo
有关)。我的目标是在列表中留下o1
的一个副本以及o2
,o4
和o6
-删除o3
和o5
,因为它们有SCT_OSC_FILLED
OrderInfo.statusCode
所以这个问题与从列表中删除无关。考虑到既定的目标,你的逻辑完全是错误的。
您想在添加项目时从列表中删除所有SCT_OSC_FILLED
项,但是您编写的代码在添加具有SCT_OSC_FILLED
的项目时从列表中删除了所有项目。你只是在测试错误的东西。
改变这
void advance(OrderInfo ordInfo, std::list <OrderInfo> ::iterator& orderIter) {
bool iterate = true;
if (ordInfo.statusCode == SCT_OSC_FILLED) {
orderIter = MasterOrders.erase(orderIter++);
iterate = false;
}
if (iterate) orderIter++;
}
void advance(OrderInfo ordInfo, std::list <OrderInfo> ::iterator& orderIter) {
bool iterate = true;
if (orderIter->statusCode == SCT_OSC_FILLED) {
orderIter = MasterOrders.erase(orderIter);
iterate = false;
}
if (iterate) orderIter++;
}
一旦您进行了更改,您可以看到ordInfo
参数未使用。添加更多的清理,最终得到这个简单得多的函数
void advance(std::list <OrderInfo> ::iterator& orderIter) {
if (orderIter->statusCode == SCT_OSC_FILLED) {
orderIter = MasterOrders.erase(orderIter);
}
else {
orderIter++;
}
}
根据cppreference.com,对已删除元素的引用和迭代器无效。在删除当前元素之前,应该先获取到下一个元素的迭代器。
在同一个页面中,cppreference给出了一个例子:
// Erase all even numbers (C++11 and later)
for (std::list<int>::iterator it = c.begin(); it != c.end(); ) {
if (*it % 2 == 0) {
it = c.erase(it);
} else {
++it;
}
}
erase返回指向下一个元素的迭代器(如果被删除的元素是最后一个元素,则为end()),因此"it = c.erase(it);"让"你;指向下一个元素,不需要对迭代器进行自增操作(使用++)。
你可以这样写:
void advance(OrderInfo ordInfo, std::list <OrderInfo> ::iterator& orderIter) {
if (ordInfo.statusCode == SCT_OSC_FILLED) {
orderIter = MasterOrders.erase(orderIter);
} else {
orderIter++;
}
}