为什么要求ForwardIterators符合默认构造模型?

10

我似乎找不到任何标准算法可以说明需要默认构造一个 ForwardIterator 的要求。

是否有任何实际原因需要这样做,或者我可以安全地忽略它?


5
无论是否存在实际原因,这都是“必需的”。因此,忽视这一要求可能会带来危险。 - Nicol Bolas
1
如果迭代器在逻辑上依赖于参数,那么另一种选择是添加默认构造函数,使对象处于无效状态,这似乎也存在风险。 - Ayjay
一种可行的替代方案是改变您的迭代器,使其不依赖于参数。将它们放在一个有效但概念上为空的状态下。 - Nicol Bolas
我认为从默认构造函数中抛出异常可能是可以的 - 否则,您真的需要在迭代器的每个函数中测试该无效状态。 - Ayjay
2
我相当确定,当他们编写DefaultConstructible要求时,他们希望构造函数能够完成。"否则,你真的需要在迭代器的每个单独函数中进行测试以检测无效状态。"不,你不需要这样做。范围之外的迭代器(包括默认构造的迭代器)不需要有效,也就是说调用*或++将产生定义行为。 - Nicol Bolas
2个回答

5

这是为了方便使用这些类型的迭代器,无论是标准算法还是客户端用户。

例如(请记住,RandomAccessIteratorForwardIterator 的子类型):

template <class RandomAccessIterator>
  void sort ( RandomAccessIterator first, RandomAccessIterator last )
{
    RandomAccessIterator pivot, i, j;
    //do your sorting algorithm        
}

如果它们不能默认构造,你需要将它们分配给firstlast才能使其编译。
不需要将其设置为默认值。任何未初始化迭代器的使用都是未定义的。虽然在调试版本中添加一些检查可能是明智的,但并非必需。
而且,你不应该在默认构造函数中抛出异常。虽然这在技术上是符合规范的,但许多算法会意外失败。

1
这是一个关于RandomAccessIterator模拟DefaultConstructible的参数,而不是ForwardIterator。虽然InputIterator不需要模拟DefaultConstructible,但为什么要模拟ForwardIterator呢? - Ayjay
1
更不用说,我不知道是否值得允许可疑的更容易实现标准算法,而牺牲了禁止所有引用和其他非默认可构造类型的不必要要求。这将对所有数据类型产生深远的影响 - 突然间,迭代器使用的所有内容现在都必须允许默认构造和“已构造但无效”的状态。 - Ayjay
这种代码违反了基于 RAII 的编码准则,因为在定义点要求初始化。 - dirkgently
1
@Ayjay - 我可能同意你的观点...但这是标准要求,你最好遵循它。在G++ STL头文件中进行快速搜索(gcc 4.7),我只发现了一个这样使用默认初始化迭代器的例子(除了检查其他迭代器的正确性和默认构造函数):在ForwardIterator partition_point(ForwardIterator first, ForwardIterator last, Predicate pred)中,而这可以很容易地避免。 - rodrigo
看起来 MSVC v10 在 adjacent_findunique 中也使用了它,这是可以避免的。多么令人沮丧啊,为了迎合标准中的一个错误而被要求向迭代器添加对无效状态的支持。叹气,C++标准再次出击。 - Ayjay

3

从我的草稿中看到:

24.2.5 前向迭代器 [forward.iterators]

1 如果一个类或内置类型 X 满足以下条件,则它满足前向迭代器的要求:

[...]

— X 满足可默认构造的要求(20.2.1),

然后:

20.2.1 模板参数的要求

2 通常情况下,不需要默认构造函数。某些容器类成员函数签名将默认构造函数指定为默认参数。如果使用默认参数调用了这些签名中的一个,则 T() 必须是一个定义良好的表达式 (8.5)。(8.3.6)

这里有两件事情需要注意:

  • 第一行告诉我们,很少需要默认构造函数(这几乎回答了你的问题)。
  • 这个要求可能是一种提示,即迭代器的语义应该与指针兼容,因为指针是可以默认构造的(意味着不会破坏现有代码)。

这似乎意味着如果您使用其中一个“特定容器类成员函数签名”调用ForwardIterator,则需要DefaultConstructible。标准是否指定了必须发生这种情况的时间? - Ayjay
@Ayjay:标准应该提供任何这样的成员函数。我不能随口说出一个名字,但如果没有任何一个,我也不会感到惊讶。这应该表明,这是为了给未来的库编写者一些喘息的机会。 - dirkgently

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接