为什么std :: list上的push_back更改使用rbegin初始化的反向迭代器? [英] Why does a push_back on an std::list change a reverse iterator initialized with rbegin?

查看:273
本文介绍了为什么std :: list上的push_back更改使用rbegin初始化的反向迭代器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据我发现的一些STL文档,在std :: list中插入或删除元素不会使迭代器无效。这意味着它允许循环一个列表(从 begin() end()),然后使用push_front添加元素。

According to some STL documentation I found, inserting or deleting elements in an std::list does not invalidate iterators. This means that it is allowed to loop over a list (from begin() to end()), and then add elements using push_front.

例如,在下面的代码中,我用元素a,b和c初始化一个列表,然后循环遍历它并执行push_front 。结果应该是cbaabc,这正是我得到的:

E.g., in the following code, I initialize a list with elements a, b and c, then loop over it and perform a push_front of the elements. The result should be cbaabc, which is exactly what I get:

std::list<std::string> testList;
testList.push_back("a");
testList.push_back("b");
testList.push_back("c");

for (std::list<std::string>::iterator itList = testList.begin(); itList != testList.end(); ++itList)
   testList.push_front(*itList);

for (std::list<std::string>::const_iterator itList = testList.begin(); itList != testList.end(); ++itList)
   std::cout << *itList << std::endl;

当我使用反向迭代器时(从 rbegin() rend())并使用push_back,我会期待类似的行为,即abccba的结果。但是,我得到不同的结果:

When I use reverse iterators (loop from rbegin() to rend()) and use push_back, I would expect similar behavior, i.e. a result of abccba. However, I get a different result:

std::list<std::string> testList;
testList.push_back("a");
testList.push_back("b");
testList.push_back("c");

for (std::list<std::string>::reverse_iterator itList = testList.rbegin(); itList != testList.rend(); ++itList)
   testList.push_back(*itList);

for (std::list<std::string>::const_iterator itList = testList.begin(); itList != testList.end(); ++itList)
   std::cout << *itList << std::endl;

结果不是 abccba code> abcccba 这是正确的有一个额外的c添加。

The result is not abccba, but abcccba. That's right there is one additional c added.

看起来像第一个push_back也改变了用rbegin()初始化的迭代器的值。在push_back之后,它不再指向列表中的第三个元素(以前是最后一个元素),而是指向第四个元素(现在是最后一个元素)。

It looks like the first push_back also changes the value of the iterator that was initialized with rbegin(). After the push_back it does not point anymore to the 3rd element in the list (which was previously the last one), but to the 4th element (which is now the last one).

我用Visual Studio 2010和GCC测试了这两者,并且两者返回相同的结果。

I tested this with both Visual Studio 2010 and with GCC and both return the same result.

这是一个错误吗?

推荐答案

标准中说,迭代器和引用仍然有效,插入物。它不说任何关于反向迭代器。 : - )

The standard says that iterators and references remain valid during an insert. It doesn't say anything about reverse iterators. :-)

rbegin()返回的 reverse_iterator 内部保持 end()的值。在 push_back()之后,这个值显然不会和以前一样。我不认为标准说应该是什么。显而易见的选择包括列表的前一个最后一个元素,或者如果它是一个固定值(如一个哨兵节点),它会停留在结尾。

The reverse_iterator returned by rbegin() internally holds the value of end(). After a push_back() this value will obviously not be the same as it was before. I don't think the standard says what it should be. Obvious alternatives include the previous last element of the list, or that it stays at the end if that is a fixed value (like a sentinel node).

技术细节: rend()返回的值不能指向 begin()因为那是无效的。因此,决定 rend()应该包含 begin()的值,位置进一步。 运算符* 补偿这一点,并访问正确的元素。

Technical details: The value returned by rend() cannot point before begin(), because that is not valid. So it was decided that rend() should contain the value of begin() and all other reverse iterators be shifted one position further. The operator* compensates for this and accesses the correct element anyway.

24.5.1的第一段反向迭代器说:

First paragraph of 24.5.1 Reverse iterators says:


类模板 reverse_iterator 是迭代器适配器,序列由其底层迭代器定义
到该序列的开始。反向
迭代器及其对应的迭代器i之间的基本关系由以下身份建立:

& *(reverse_iterator(i))==& * i-1)

Class template reverse_iterator is an iterator adaptor that iterates from the end of the sequence defined by its underlying iterator to the beginning of that sequence. The fundamental relation between a reverse iterator and its corresponding iterator i is established by the identity:
&*(reverse_iterator(i)) == &*(i - 1).

这篇关于为什么std :: list上的push_back更改使用rbegin初始化的反向迭代器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆