假设我使用两个索引之一迭代boost::multi_index
。然后,如果我开始使用其他索引进行迭代并根据某些条件擦除元素,那么这会使上部迭代器失效吗?
如,
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <string>
#include <iostream>
using namespace boost::multi_index;
using namespace std;
struct person {
string name;
string last_name;
int age;
};
typedef multi_index_container<
person,
indexed_by<
ordered_non_unique<member<person, string, &person::name> >,
ordered_non_unique<member<person, int, &person::age> >,
sequenced<>
>
> PersonCollection;
int main()
{
PersonCollection pc;
//insert some elements into pc
struct person kk = {"John", "Doe", 15};
pc.insert(kk);
kk = {"John", "Doe2", 17};
pc.insert(kk);
kk = {"John", "Doe3", 34};
pc.insert(kk);
kk = {"John", "Smith", 34};
pc.insert(kk);
auto &index0 = pc.get<0>();
auto range0 = index0.equal_range("John");
while (range0.first != range0.second) {
auto &index1 = pc.get<1>();
auto range1 = index1.equal_range(34);
while (range1.first != range1.second) {
if (range1.first->last_name == "Smith")
range1.first = index1.erase(range1.first);
else
++range1.first;
}
++range0.first;
}
return 0;
}
那么在这种情况下,range0
迭代器是否始终有效?谢谢!
答案 0 :(得分:1)
你的循环可能存在根本缺陷。我认为这是因为你使用了令人困惑的名字(range0
等)。外部循环与内部循环无关,因此,您可以将其删除(节省时间进行无用的重复)。这是一个澄清的重写:
auto& ageIdx = pc.get<byAge>();
auto namerange = pc.get<byName>().equal_range("John");
for (auto name_it = namerange.first, end = namerange.second; name_it != end; ++name_it) {
auto agerange = ageIdx.equal_range(34);
for (auto age_it = agerange.first, end = agerange.second; age_it != end;) {
if (age_it->last_name == "Smith")
age_it = ageIdx.erase(age_it);
else
++age_it;
}
}
确实这是不安全的。 name_it
可能无效。解决它:
for (auto name_it = namerange.first, end = namerange.second; name_it != end;) {
++name_it;
请注意,该代码将删除删除&#39; Ruby Smith(34岁)&#39;正好。约翰&#39;从不使用标准,所以:
更好的是,将其修改为等效的:
auto agerange = pc.get<byAge>().equal_range(34);
for (auto age_it = agerange.first, end = agerange.second; age_it != end;) {
std::cout << *age_it << "\n";
if (age_it->last_name == "Smith")
age_it = ageIdx.erase(age_it);
else
++age_it;
}
看起来你想删除一些&#34; primary&#34; key(name,last_name,age)。说出你的意思:
pc.erase(pc.find(boost::make_tuple("Smith", "John", 34))); // just the one
代码的全部。
<强> Live On Coliru 强>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <string>
#include <iostream>
struct person {
std::string name;
std::string last_name;
int age;
friend std::ostream& operator<<(std::ostream& os, person const& p) {
return os << "{" << p.name << ", " << p.last_name << ", " << p.age << "}";
}
};
namespace bmi = boost::multi_index;
typedef bmi::multi_index_container<
person,
bmi::indexed_by<
bmi::ordered_unique<bmi::tag<struct primaryKey>,
bmi::composite_key<person,
bmi::member<person, std::string, &person::last_name>,
bmi::member<person, std::string, &person::name>,
bmi::member<person, int, &person::age>
>
>,
bmi::ordered_non_unique<bmi::tag<struct byAge>, bmi::member<person, int, &person::age> >
>
> PersonCollection;
int main() {
PersonCollection pc {
person { "John", "Lennon", 34 },
person { "Elliot", "Gardiner", 72 },
person { "John", "Smith", 34 },
person { "Lucy", "Greenstle", 34 },
person { "Gold", "Smith", 34 },
person { "Nicolai", "Josuttis", 42 }
};
auto& idx = pc.get<primaryKey>();
// print
std::copy(pc.begin(), pc.end(), std::ostream_iterator<person>(std::cout << "\n", "; "));
pc.erase(pc.find(boost::make_tuple("Smith", "John", 34))); // just the one
// print
std::copy(pc.begin(), pc.end(), std::ostream_iterator<person>(std::cout << "\n", "; "));
auto range = idx.equal_range(boost::make_tuple("Smith", "John")); // any age
for (auto f=range.first, l=range.second; f!=l;)
f = idx.erase(f);
// print
std::copy(pc.begin(), pc.end(), std::ostream_iterator<person>(std::cout << "\n", "; "));
range = idx.equal_range(boost::make_tuple("Smith")); // any age/first name
for (auto f=range.first, l=range.second; f!=l;)
f = idx.erase(f);
// print
std::copy(pc.begin(), pc.end(), std::ostream_iterator<person>(std::cout << "\n", "; "));
}
打印:
{Elliot, Gardiner, 72}; {Lucy, Greenstle, 34}; {Nicolai, Josuttis, 42}; {John, Lennon, 34}; {Gold, Smith, 34}; {John, Smith, 34};
{Elliot, Gardiner, 72}; {Lucy, Greenstle, 34}; {Nicolai, Josuttis, 42}; {John, Lennon, 34}; {Gold, Smith, 34};
{Elliot, Gardiner, 72}; {Lucy, Greenstle, 34}; {Nicolai, Josuttis, 42}; {John, Lennon, 34}; {Gold, Smith, 34};
{Elliot, Gardiner, 72}; {Lucy, Greenstle, 34}; {Nicolai, Josuttis, 42}; {John, Lennon, 34};