练习9.31:第316页中删除偶值元素并复制奇值元素的程序不能用于list或者forward_list。为什么?修改程序,使之也能用于这些类型。
316页代码:
//傻瓜循环,删除偶数元素,复制奇数元素
vector<int> vi = {0,1,2,3,4,5,6,7,8,9};
auto iter = vi.begin(); //调用begin而不是cbegin,因为我们要改变vi
while(iter != vi.end()){
if(*iter % 2){
iter = vi.insert(iter, *iter);//复制当前元素
iter += 2; //向前移动迭代器,跳过当前元素以及插入到它之前的元素
} else
iter = vi.erase(iter); //删除偶数元素
// 不应向前移动迭代器,iter指向我们删除的元素之后的元素
}
insert 在指定位置之前插入一个元素
insert_after 在指定位置之后插入
二者都是返回 最后插入的那个元素的迭代器。
答:不能用于list是因为 list的迭代器不支持 算数加的操作 只能每次加一个
不能用于forward_list 除了上述原因 还因为它要使用自己特定版本的insert_after和erase_after
修改 适合list:
//傻瓜循环,删除偶数元素,复制奇数元素
list<int> vi = {0,1,2,3,4,5,6,7,8,9};
auto iter = vi.begin(); //调用begin而不是cbegin,因为我们要改变vi
while(iter != vi.end()){
if(*iter % 2){
iter = vi.insert(iter, *iter);//复制当前元素
iter ++; //向前移动迭代器,跳过当前元素以及插入到它之前的元素
iter ++;
} else
iter = vi.erase(iter); //删除偶数元素
// 不应向前移动迭代器,iter指向我们删除的元素之后的元素
}
修改 适合forward_list:
//傻瓜循环,删除偶数元素,复制奇数元素
forward_list<int> vi = {0,1,2,3,4,5,6,7,8,9};
auto iter = vi.begin(); //调用begin而不是cbegin,因为我们要改变vi
auto prev = vi.before_begin();
while(iter != vi.end()){
if(*iter % 2){
iter = vi.insert_after(iter, *iter);//复制当前元素
iter ++; //向前移动迭代器,跳过当前元素以及插入到它之前的元素
prev++;
prev++;
} else
iter = vi.erase_after(prev); //删除偶数元素
// 不应向前移动迭代器,iter指向我们删除的元素之后的元素
}
练习9.32:在第316页的程序中,向下面语句这样调用insert是否合法?如果不合法,为什么?
iter = vi.insert(iter, *iter++);
答:不合法 因为 insert操作改变了容器的大小 迭代器将失效 再进行自加操作将会报错。
练习9.33:在本节最后一例中,如果不将insert的结果赋予begin,将会发生什么?编写程序,去掉此赋值语句,验证你的答案。
答:没有必要验证 删除之后肯定迭代器失效 然后运行中断
练习9.34: 假定vi是一个保存int的容器,其中有偶数值也有奇数值,分析下面循环的行为,然后编写程序验证你的分析是否正确。
iter = vi.begin();
while(iter != vi.end()){
if(*iter % 2)
iter = vi.insert(iter, *iter);
++iter;
}
答:原书代码里面自加没有进循环 所以是死循环
进循环后 由于只加了一次 所以 如果有一个奇数 那依然每次都是死循环。