C++ 为什么迭代器需要是默认可构造的
前向、双向和随机访问类别的迭代器需要是默认可构造的C++ 为什么迭代器需要是默认可构造的,c++,stl,iterator,language-lawyer,standard-library,C++,Stl,Iterator,Language Lawyer,Standard Library,前向、双向和随机访问类别的迭代器需要是默认可构造的 为什么会这样,为什么输入和输出运算符不必是默认可构造的 前向迭代器和更强的迭代器需要引用某些外部序列(请参见[Forward.iterators]/6,其中表示“如果a和b都是可取消引用的,那么a==b当且仅当*a和*b绑定到同一个对象。”) 这意味着它们通常只是其他对象的轻量级句柄(例如,指向容器中元素或节点的指针),因此几乎没有理由不要求它们可以默认构造(即使默认构造创建了一个单一迭代器,在分配新值之前不能用于任何事情)。所有非病态*前向迭
为什么会这样,为什么输入和输出运算符不必是默认可构造的 前向迭代器和更强的迭代器需要引用某些外部序列(请参见[Forward.iterators]/6,其中表示“如果
a
和b
都是可取消引用的,那么a==b
当且仅当*a
和*b
绑定到同一个对象。”)
这意味着它们通常只是其他对象的轻量级句柄(例如,指向容器中元素或节点的指针),因此几乎没有理由不要求它们可以默认构造(即使默认构造创建了一个单一迭代器,在分配新值之前不能用于任何事情)。所有非病态*前向迭代器都可能支持默认构造,依靠它,一些算法更容易实现
仅满足输入迭代器或输出迭代器要求的迭代器(没有更强大的要求)可能包含由operator++
修改的状态,因此可能无法默认构造该状态。没有只在输入/输出迭代器上运行的算法需要默认构造它们,因此不需要这样做
- 在这里找出“没有真正的苏格兰人”的论点;)李>
class MyClass
{
public:
void myFunction(ForwardIterator &i)
{
//do some code here
savedIter = i;
//do some code here
}
private:
ForwardIterator savedIter;
}
根据定义,这是有效的,因为我们可以将迭代器保存一段时间,因为要求该迭代器的副本保持有效。(至少在迭代器指向的数据结构被破坏之前)
然而,对于要创建的这个类,ForwardIterator显然需要一个默认构造函数…可能是因为许多人用它来编写
std::vector::iterator代码>在for循环之外,以避免超出推荐的78个字符的线宽。如果要使用std::vector::iterator,则它=container.begin()
那么for循环就没有那么性感了:for(;it!=container.end();++it)
。不幸的是,有些算法的实现方式要求默认的可构造性。原则上,这似乎是避免过早分配的合理要求,但在我看到的示例中,它可以很容易地避免。我最近尝试实现一个迭代器,并要求默认可构造,但不幸的是添加了一个间接级别,否则就没有必要了。因此,我一直在为间接寻址的额外级别付费,我认为这个要求非常不幸,因为它有一个令人讨厌的隐藏成本;他们通常有一个很好的理由。对我来说,这似乎是非常特殊的STL容器。很容易想到一些自定义迭代器,它比std::vector::iterator
存储更多的状态,并且这种状态也不能凭空创建。为什么输入和输出迭代器不应该是单数的呢?(事实上,流迭代器是默认可构造的。)@MarkRansom注意,SGI STL all迭代器必须是默认可构造的,该标准实际上删除了对输入和输出迭代器的要求。在libstdc++(因此可能也在SGI STL中)中,至少std::search
,std::partition_点
和std::minmax_元素
依赖于默认构造正向迭代器<代码>标准::罗塔