在STL库中,一些容器具有迭代器,并且通常认为它们是迭代这些容器的优越方式,而不是简单的循环,例如
for ( int i=0; i < vecVector.size(); i++ )
{
..
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以告诉我为什么以及在什么情况下我应该使用迭代器以及在什么情况下上面的代码片段?
我知道这可能是一个愚蠢的问题..我什么时候需要编写自己的迭代器?是在设计我自己的容器类时吗?还有其他什么时候我想创建自己的迭代器吗?
例子将被挪用.
-Jon
基于以下问题:检查一个字符串是否是其他字符串的旋转
我正在考虑制作一个带有范围的循环迭代器类型,并且能够像这样解决上述问题:
std::string s1 = "abc" ;
std::string s2 = "bca" ;
std::size_t n = 2; // number of cycles
cyclic_iterator it(s2.begin(),s2.end(),n);
cyclic_iterator end;
if (std::search(it, end, s1.begin(),s1.end()) != end)
{
std::cout << "s1 is a rotation of s2" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
我的问题,是否已经有这样的东西?我检查了Boost和STL,但都没有确切的实现.
我有一个简单的手写(源自一个std::forward_iterator_tag专门的版本std::iterator),但宁可使用已经制作/测试过的实现.
STL通常定义一个输出迭代器,如下所示:
template<class Cont>
class insert_iterator
: public iterator<output_iterator_tag,void,void,void,void> {
// ...
Run Code Online (Sandbox Code Playgroud)
为什么输出迭代器定义value_type为void?算法知道它应该输出什么类型的值会很有用.
例如,一个将URL查询"key1=value1&key2=value2&key3=value3"转换为包含键值字符串元素的任何容器的函数.
template<typename Ch,typename Tr,typename Out>
void parse(const std::basic_string<Ch,Tr>& str, Out result)
{
std::basic_string<Ch,Tr> key, value;
// loop over str, parse into p ...
*result = typename iterator_traits<Out>::value_type(key, value);
}
Run Code Online (Sandbox Code Playgroud)
这提示的SGI参考页面value_type是因为无法取消引用输出迭代器.但这不是唯一的用途value_type:我可能想要实例化一个以便将它分配给迭代器.
有什么替代方法可以用输出迭代器构造输出值?我考虑过两种方法:
pair<string,string>,或者从中可以转换的类型.我想知道如果没有这个要求我能做到,也许允许任何可以从两个构造的元素std::string.鉴于这段代码:
from glob import glob, iglob
for fn in glob('/*'):
print fn
print ''
for fn in iglob('/*'):
print fn
Run Code Online (Sandbox Code Playgroud)
阅读glob 的文档我看到glob()返回一个基本的文件列表,iglob是一个Iterator.但是,我能够迭代两者,并且每个文件返回相同的文件列表.
我已经阅读了有关Iterator的文档,但它还没有真正了解这个主题!
那么iglob()返回一个Iterator会给我带来glob()的列表有什么好处呢?我是否能从我的老朋友那里获得额外的功能?
假设我有一个[acme]对象流,我想通过API公开.我有两个选择,回调和迭代器.
// API #1
// This function takes a user-defined callback
// and invokes it for each object in the stream.
template<typename CallbackFunctor>
void ProcessAcmeStream(CallbackFunctor &callback);
Run Code Online (Sandbox Code Playgroud)
// API #2
// Provides the iterator class AcmeStreamIterator.
AcmeStreamIterator my_stream_begin = AcmeStreamIterator::begin();
AcmeStreamIterator my_stream_end = AcmeStreamIterator::end();
Run Code Online (Sandbox Code Playgroud)
API#1从用户手中获取程序的控制流,并且在整个流被消耗之前不会返回(暂时忘记异常).
API#2保留用户手中的控制流,允许用户自己前进流.
API#1感觉更高级别,允许用户立即跳转到业务逻辑(回调函子).另一方面,API#2感觉更灵活,允许用户更低级别的控制.
从设计的角度来看,我应该选择哪一个?我还没有看到更多的利弊吗?未来有哪些支持/维护问题?
上C++最流行的交迭代器失效规则声称,目前还不清楚,如果在过去的最端迭代器(即,那些由返回end(),cend(),rend(),和crend())根据相同的规则正常迭代器,这点在元件被无效容器.这些针对2003和2011 C++的声明,推迟到讨论End迭代器失效规则的帖子,其中接受的答案表明2003标准在这个问题上是模棱两可的.这一结论是基于23.1/10评论(在的情况下swap(),这似乎暗示,当规范没有明确提及过去的最末端迭代器失效,他们可能会失效).
对该帖子的问题的评论(由mike-seymour提出)表明C++ 11在这个问题上是明确的,在deques 的情况下.我的问题是关于所有容器:
换句话说,
我有一个std :: unordered_map,我将从via迭代中删除元素.
auto itr = myMap.begin();
while (itr != myMap.end()) {
if (/* removal condition */) {
itr = myMap.erase(itr);
} else {
++itr;
}
}
Run Code Online (Sandbox Code Playgroud)
我想阻止地图执行任何昂贵的操作,直到我完成删除我需要删除的所有元素.我有一个有效的顾虑吗?我误解了内部存储的工作原理吗?
看看下面的课程我做了:
public class FibonacciSupplier implements Iterator<Integer> {
private final IntPredicate hasNextPredicate;
private int beforePrevious = 0;
private int previous = 1;
private FibonacciSupplier(final IntPredicate hasNextPredicate) {
this.hasNextPredicate = hasNextPredicate;
}
@Override
public boolean hasNext() {
return hasNextPredicate.test(previous);
}
@Override
public Integer next() {
int result = beforePrevious + previous;
beforePrevious = previous;
previous = result;
return result;
}
public static FibonacciSupplier infinite() {
return new FibonacciSupplier(i -> true);
}
public static FibonacciSupplier finite(final IntPredicate predicate) {
return new FibonacciSupplier(predicate);
} …Run Code Online (Sandbox Code Playgroud) 以下Rust代码成功编译:
struct StructNothing;
impl<'a> StructNothing {
fn nothing(&'a mut self) -> () {}
fn twice_nothing(&'a mut self) -> () {
self.nothing();
self.nothing();
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我们尝试将其打包成特征,则会失败:
pub trait TraitNothing<'a> {
fn nothing(&'a mut self) -> () {}
fn twice_nothing(&'a mut self) -> () {
self.nothing();
self.nothing();
}
}
Run Code Online (Sandbox Code Playgroud)
这给了我们:
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/lib.rs:6:9
|
1 | pub trait TraitNothing<'a> {
| -- lifetime `'a` defined here
... …Run Code Online (Sandbox Code Playgroud)