我使用std :: list遇到了一些奇怪的行为。问题是,当我删除列表中的当前元素时,它会使该元素无效。当我使用for( auto& iter : list)
循环遍历元素时,它会卡在应该删除的元素上。我有一个最小的可编辑示例来说明这一点:
#include <iostream>
#include <list>
#include <memory>
int main() {
std::list<unsigned int> wholeNumbers;
while( wholeNumbers.size() < 20 ) {
wholeNumbers.push_back( wholeNumbers.size() );
}
for( auto wholeNumber : wholeNumbers ) {
std::cout << "Deleting entries. Value is: " << wholeNumber << std::endl;
std::cout << "Old size: " << wholeNumbers.size() << std::endl;
wholeNumbers.remove( wholeNumber );
std::cout << "New size: " << wholeNumbers.size() << std::endl;
}
}
期望的结果是吐出递增值和递减的大小。但是,我遇到的结果如下:
Deleting entries. Value is: 0
Old size: 20
New size: 19
Deleting entries. Value is: 0
Old size: 19
New size: 19
Deleting entries. Value is: 0
Old size: 19
New size: 19
Deleting entries. Value is: 1901208
Old size: 19
New size: 19
Deleting entries. Value is: 0
Old size: 19
New size: 19
Deleting entries. Value is: 0
Old size: 19
New size: 19
Deleting entries. Value is: 0
Old size: 19
New size: 19
Deleting entries. Value is: 1901208
Old size: 19
New size: 19
然后无限期地重复。
我的编译器信息是:gcc version 5.3.0 (x86_64-posix-sjlj-rev0, Built by MinGW-W64 project)
如果我错误地认为这应该按照我的意愿行事,我很好奇。
致以最诚挚的问候,
答案 0 :(得分:2)
来自{{3}}:
擦除元素的引用和迭代器无效。
基于for循环的范围使用隐式迭代器。 remove
正在删除迭代器指向的元素,因此它变为无效,并且您有未定义的行为,它可能会擦除您的硬盘驱动器。
相反,获取一个显式迭代器。调用erase
,而不是remove
,并将迭代器设置为erase
的返回值以继续迭代(返回值:&#34;迭代器跟随最后删除的元素。&#34; )
答案 1 :(得分:1)
迭代器有效性:引用函数删除的元素的迭代器,指针和引用无效。
基于for循环的范围在内部使用迭代器,所以你做的是使迭代器无效,因此你期望的行为不是你所期望的。
与std::remove不同,http://en.cppreference.com/w/cpp/container/list/erase只是将元素移动到容器的末尾并返回指向第一个元素的指针&#34;删除&#34; - 因此需要着名的erase-remove-idiom-list :: remove实际上调用了析构函数。
答案 2 :(得分:0)
在第一次迭代中,您成功删除了第一个元素,以及第一个元素和std :: list的第二个元素之间的连接。所以它在第二次迭代中遇到了问题,因为for循环无法将指向具有未定义值的已删除元素的auto wholeNumber
设置为std :: list的第二个元素。