逐步删除列表元素
Erasing list elements step by step
我想一个一个地删除列表元素。在删除任何列表元素之前,我想查看整个列表。
#include <iostream>
#include <list>
int main()
{
std::list<int>numbers{0,1,2,3,4,5,6,7,8,9};
auto it=numbers.begin();
for(int i=0;i<10;i++){
for(auto j:numbers)
std::cout<<j<<" ";
std::cout<<std::endl;
it=numbers.erase(it);
it++;
}
return 0;
}
输出:
0 1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 3 4 5 6 7 8 9
1 3 5 6 7 8 9
1 3 5 7 8 9
1 3 5 7 9
double free or corruption (out)
为什么这个过程只处理了一半的元素。如何逐步删除所有列表元素?我知道我可以使用 numbers.clear()
,但我不需要那个。
另外,为什么擦除不按顺序进行? (先删0,再删2,再删4)?
it=numbers.erase(it);
it++;
在第一行中,列表删除了迭代器指向的元素和 returns 指向下一个元素的迭代器。旧元素不再存在,传递给 erase()
的 it
变得无效。这就是为什么你必须使用返回的迭代器,它指向下一个元素。
然后第二行跳过该行,迭代器不再指向新列表的开头。
您正在从列表中每隔一个元素删除一次:擦除、跳过、擦除、跳过、擦除、跳过……
#include <algorithm>
#include <iostream>
#include <iterator>
#include <list>
template <typename Container>
void print(const Container& container, std::ostream& sout = std::cout) {
std::copy(std::begin(container), std::end(container),
std::ostream_iterator<typename Container::value_type>(sout, " "));
sout << '\n';
}
int main() {
std::list<int> numbers{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
// Note that the update action is skipped
for (auto it = numbers.begin(); it != numbers.end();) {
print(numbers);
it = numbers.erase(it);
}
return 0;
}
这只能用迭代器来完成。我将打印移到了它自己的功能中。这里的关键是循环声明不再负责更新迭代器,因为它现在发生在循环体中。阅读 std::list<T>::erase()
告诉我们函数 returns 是一个迭代器,它指向被擦除后的元素。由于我们从头开始擦除,所以擦除动作自然会遍历整个列表。
同样重要的是要注意循环必须以这种方式完成。从列表中删除会使列表的所有 pre-existing 迭代器失效。现在唯一有效的是 erase() 函数返回的迭代器。
问题出在这两行
it=numbers.erase(it);
it++;
函数,list::erase
,returns一个指向最后一个被擦除元素之后的元素的迭代器。在这里,您的代码从列表中删除项目并将 it
设置为列表中的下一个元素。然后指令 it++
将迭代器再前进一位,因此跳过列表中的一项。
简单的解决方案是注释掉 it++
行:
#include <iostream>
#include <list>
int main()
{
std::list<int>numbers{0,1,2,3,4,5,6,7,8,9};
auto it=numbers.begin();
for(int i=0;i<10;i++)
{
for(auto j:numbers)
std::cout<<j<<" ";
std::cout<<std::endl;
it=numbers.erase(it);
//it++;
}
return 0;
}
这给出了这个输出:
0 1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
2 3 4 5 6 7 8 9
3 4 5 6 7 8 9
4 5 6 7 8 9
5 6 7 8 9
6 7 8 9
7 8 9
8 9
9
我想一个一个地删除列表元素。在删除任何列表元素之前,我想查看整个列表。
#include <iostream>
#include <list>
int main()
{
std::list<int>numbers{0,1,2,3,4,5,6,7,8,9};
auto it=numbers.begin();
for(int i=0;i<10;i++){
for(auto j:numbers)
std::cout<<j<<" ";
std::cout<<std::endl;
it=numbers.erase(it);
it++;
}
return 0;
}
输出:
0 1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 3 4 5 6 7 8 9
1 3 5 6 7 8 9
1 3 5 7 8 9
1 3 5 7 9
double free or corruption (out)
为什么这个过程只处理了一半的元素。如何逐步删除所有列表元素?我知道我可以使用 numbers.clear()
,但我不需要那个。
另外,为什么擦除不按顺序进行? (先删0,再删2,再删4)?
it=numbers.erase(it);
it++;
在第一行中,列表删除了迭代器指向的元素和 returns 指向下一个元素的迭代器。旧元素不再存在,传递给 erase()
的 it
变得无效。这就是为什么你必须使用返回的迭代器,它指向下一个元素。
然后第二行跳过该行,迭代器不再指向新列表的开头。
您正在从列表中每隔一个元素删除一次:擦除、跳过、擦除、跳过、擦除、跳过……
#include <algorithm>
#include <iostream>
#include <iterator>
#include <list>
template <typename Container>
void print(const Container& container, std::ostream& sout = std::cout) {
std::copy(std::begin(container), std::end(container),
std::ostream_iterator<typename Container::value_type>(sout, " "));
sout << '\n';
}
int main() {
std::list<int> numbers{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
// Note that the update action is skipped
for (auto it = numbers.begin(); it != numbers.end();) {
print(numbers);
it = numbers.erase(it);
}
return 0;
}
这只能用迭代器来完成。我将打印移到了它自己的功能中。这里的关键是循环声明不再负责更新迭代器,因为它现在发生在循环体中。阅读 std::list<T>::erase()
告诉我们函数 returns 是一个迭代器,它指向被擦除后的元素。由于我们从头开始擦除,所以擦除动作自然会遍历整个列表。
同样重要的是要注意循环必须以这种方式完成。从列表中删除会使列表的所有 pre-existing 迭代器失效。现在唯一有效的是 erase() 函数返回的迭代器。
问题出在这两行
it=numbers.erase(it);
it++;
函数,list::erase
,returns一个指向最后一个被擦除元素之后的元素的迭代器。在这里,您的代码从列表中删除项目并将 it
设置为列表中的下一个元素。然后指令 it++
将迭代器再前进一位,因此跳过列表中的一项。
简单的解决方案是注释掉 it++
行:
#include <iostream>
#include <list>
int main()
{
std::list<int>numbers{0,1,2,3,4,5,6,7,8,9};
auto it=numbers.begin();
for(int i=0;i<10;i++)
{
for(auto j:numbers)
std::cout<<j<<" ";
std::cout<<std::endl;
it=numbers.erase(it);
//it++;
}
return 0;
}
这给出了这个输出:
0 1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
2 3 4 5 6 7 8 9
3 4 5 6 7 8 9
4 5 6 7 8 9
5 6 7 8 9
6 7 8 9
7 8 9
8 9
9