【发布时间】:2011-09-07 23:46:33
【问题描述】:
注意:这不是我应该“使用列表还是双端队列”的问题。面对insert(),这是一个关于迭代器有效性的问题。
这可能是一个简单的问题,我只是太密集了,看不到正确的方法。我正在将网络流量缓冲区(无论好坏)实现为std::list<char> buf,并将我当前的读取位置保持为迭代器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 在列表中被破坏,但点到双端队列中的下一个元素。 这是标准保证吗?
(根据cplusplus,任何 deque::insert() invalidate 所有迭代器。这不好。也许使用计数器比迭代器更好地跟踪双端队列中的位置?)
【问题讨论】:
-
使用双端队列,您将始终从头读取并在末尾插入...无需跟踪特定的读取位置。不,这不是标准保证;特别是,如果 dequeue 恰好重新分配,则前一个
end()几乎肯定会引用已释放的内存。 -
只是提到
deque,您可以保留当前位置的数字索引而不是迭代器。 -
最好不要依赖测试行为;它可以演示什么不起作用,但不保证任何看起来都有效。例如,如果存储没有重新分配,迭代器可能仍然有效,但您不能依赖它。
-
谢谢大家——是的,我确实会简单地存储一个数字读取位置。尼莫:我不能总是在前面看书。我想我可以立即删除我从前面读取的数据,但有一些原因我可能只想在一些处理后删除。
-
我认为你的问题标题应该是“保持 std::deque 迭代器通过插入有效”,因为
std::list迭代器通过任何插入。另外,如果您想知道是否应该使用list或deque,我说使用vector和整数索引(只要数据大小相对较小)。顺便说一句,漂亮的dopefish。