繁体   English   中英

通过插入保持 std::list 迭代器有效

[英]Keeping std::list iterators valid through insertion

注意:这不是我应该“使用列表还是双端队列”的问题。 面对insert() ,这是一个关于迭代器有效性的问题。


这可能是一个简单的问题,我太密集了,看不到正确的方法。 我正在实现(无论好坏)网络流量缓冲区作为std::list<char> buf ,并且我将当前读取的 position 维护为迭代器readpos

当我添加数据时,我会做类似的事情

buf.insert(buf.end(), newdata.begin(), newdata.end());

我现在的问题是,如何保持readpos迭代器有效? 如果它指向旧buf的中间,那么它应该没问题(通过 std::list 的迭代器保证),但通常我可能已经读取并处理了所有数据并且我有readpos == buf.end() 插入后,我希望readpos始终指向下一个未读字符,在插入的情况下应该是第一个插入的字符。

有什么建议么? (没有将缓冲区更改为std::deque<char> ,这似乎更适合该任务,如下所示。)

更新:通过 GCC4.4 的快速测试,我观察到 deque 和 list 在readpos = buf.end()方面的行为不同:在最后插入后, readpos 在列表中被破坏,但指向 a 中的下一个元素双端队列。 这是标准保证吗?

(根据cplusplus ,任何 deque::insert() 都使所有迭代器无效。这不好。也许使用计数器比迭代器更好地跟踪双端队列中的 position?)

if (readpos == buf.begin())
{
    buf.insert(buf.end(), newdata.begin(), newdata.end());
    readpos = buf.begin();
}
else
{
    --readpos;
    buf.insert(buf.end(), newdata.begin(), newdata.end());
    ++readpos;
}

不优雅,但它应该工作。

来自http://www.sgi.com/tech/stl/List.html

“列表具有重要的属性,即插入和拼接不会使列表元素的迭代器无效,即使删除也只会使指向被删除元素的迭代器无效。”

因此, readpos在插入后应该仍然有效。

然而...

std::list< char >是解决此问题的一种非常低效的方法。 您存储在std::list中的每个字节都需要一个指针来跟踪字节,加上列表节点结构的大小,通常还有两个指针。 也就是说,至少有 12 或 24 个字节(32 或 64 位)的 memory 用于跟踪单个数据字节。

std::deque< char>可能是一个更好的容器。 std::vector一样,它在后面提供恒定时间插入,但它也在前面提供恒定时间删除。 最后,像std::vector std::deque是一个随机访问容器,因此您可以使用偏移量/索引而不是迭代器。 这三个特点使它成为一个有效的选择。

我确实很密集。 该标准为我们提供了我们需要的所有工具。 具体来说,序列容器要求 23.2.3/9 说:

a.insert(p, i, j)返回的迭代器指向插入到a中的第一个元素的副本,如果i == j则指向p

接下来, list::insert的描述说 (23.3.5.4/1):

不影响迭代器和引用的有效性。

所以事实上,如果pos是我当前正在使用的列表中的迭代器,我可以说:

auto it = buf.insert(buf.end(), newdata.begin(), newdata.end());

if (pos == buf.end()) { pos = it; }

我的列表中新元素的范围是[it, buf.end()) ,尚未处理的元素的范围是[pos, buf.end()) 这是因为如果pos在插入之前等于buf.end() ,那么它仍然在插入之后,因为插入不会使任何迭代器失效,甚至不会使结尾失效。

list<char>是一种非常低效的存储字符串的方法。 它可能比字符串本身大 10-20 倍,而且您正在为每个字符追逐一个指针......

您是否考虑过使用std::dequeue<char>代替?

[编辑]

要回答您的实际问题,添加和删除元素不会使list中的迭代器无效......但是end()仍然是end() 因此,您需要在插入新元素以更新您的readpos迭代器时将其作为特殊情况进行检查。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM