我正在编写一个测试程序,发现了std::list
行为的一个非常有趣的案例。
#include <list>
#include <algorithm>
#include <iostream>
int main()
{
std::list<int> mylist;
std::list<int>::iterator iter;
for(int i=3; i<10; ++i){
mylist.push_back(i);
}
iter = mylist.begin();
iter--;
iter--;
std::cout<<*iter<< std::endl;
std::cout<<std::distance(mylist.end(), mylist.begin())<<std::endl;
}
输出结果为:
9
1
如果我没有弄错,这种行为与循环列表有关。我从未见过论坛,书籍或讨论,其中提到标准列表是循环列表。我的GCC版本是4.1.2。
我是对的吗?标准std::list
是循环列表吗?
答案 0 :(得分:15)
不,std::list
不是循环的。递减迭代器时,代码具有未定义的行为。当您致电std::distance(mylist.end(), mylist.begin())
时,它也会有未定义的行为,因为无法通过递增mylist.begin()
来访问mylist.end()
。
请注意,当您调用未定义的行为时,std::list
可能看起来是循环的,因为&#34; std :: list看起来是循环的&#34;当行为未定义时,适合允许的行为范围。这个范围是任何行为。
答案 1 :(得分:2)
即使它在此实现中是循环 ,您也不必依赖它,因为标准不保证此属性。
您的开始指针的递减也是未定义的行为以及std::distance
调用。
确实可以通过以下可能具有可观察结果的方式实施列表:
list
head --> listelem1 (or elEnd)
begin() return head;
end() return head->prev;
listelem1 listelem2 listelem3 elEnd
ptr = d1 ptr = d2 ptr = d3 ptr = nullptr
next = le2 next = le3 next = elEnd next = le1
prev = elEnd prev = le1 prev = le2 prev = le3
但是,只要他遵循标准的接口和行为要求,这取决于库的实现者。