-1

我得到了一个任务来实现一个带有迭代器的模板数组,并覆盖了我的迭代器的一些运算符,我有几个问题。据我了解,std 随机访问迭代器允许你超过数组。它是否允许获取它持有的超过 Size 的值?它是否允许用户覆盖该内存?

对于我的实现,我应该允许访问大小吗?我应该允许从大小中获取数据吗?我应该允许对其进行任何更改吗?

在这种情况下,什么被认为是好的编程?

任何帮助都感激不尽

4

5 回答 5

2

迭代器执行的运行时检查量取决于它们。库std迭代器通常很少做运行时检查,因为std库的设计理念的一部分是通过高级类型检查提供接近手工编码的容器性能。

但是,许多std库实现包括多个级别的运行时检查作为调试构建的选项。这意味着,如果您要求获取无效迭代器的内容,std迭代器将调用未定义的行为,并且可能会给您一些超出缓冲区末尾的随机内存的内容,或者有时是段错误。如果你写,它会很高兴地写到你不允许写的那个内存。

在编写迭代器时,最好在迭代器中包含调试工具,因为您不会在第一次正确编写它。虽然std库迭代器调试工具主要是为了捕捉迭代器的用户犯了错误,但你想要做的那种检查来确定迭代器的作者(即你)是否犯了错误是相似的。

包括或不包括此类检查都是很好的做法。在开发迭代器时,你绝对应该包括这样的检查(连接到异常、断言,甚至只是一个错误日志系统——cerr在这种情况下算作错误日志),即使这些检查可以在“生产”代码。

于 2013-06-04T11:48:21.783 回答
1

大小对于溢出并不重要。随机访问迭代器意味着您可以使用 operator[] 查找元素,或者使用 operator += 或 + 或 -= 或 - 以任意数量递增或递减

在此处查看所有需要的操作http://www.cplusplus.com/reference/iterator/RandomAccessIterator/

于 2013-06-04T11:45:05.553 回答
1

在标准 C++ 库(以前称为 STL)中,迭代器执行范围检查的方式与 C 指针中不执行范围检查的方式相同。通过指向超出分配边界的迭代器访问内存是未定义的行为,就像通过指向超出分配边界的指针访问内存是未定义的行为一样。您应该在设计迭代器时遵循相同的原则,即您应该对数据访问执行无边界检查。

于 2013-06-04T11:46:46.067 回答
1

我认为您可能对您的作业阅读过多,但您的问题确实值得考虑。

首先,有几点考虑:

  • 有变异迭代器和非变异迭代器(iterator以及const_iterator一般的嵌套类型),前者允许写入指向的元素,而后者不允许。
  • 迭代器应该是轻量级的,它们在许多算法中被一遍又一遍地复制

现在,关于您的问题,确实有一个关于是否执行边界检查的设计决定。

通常,C++ 中的迭代器非常轻量级,以至于它们根本不执行边界检查。这是效率的名称,你不用为你不使用的哲学付费。如果用户过冲……她将成为Undefined Behavior的牺牲品,那任何事情都可能发生。

然而,大多数(如果不是全部)STL 实现也会承认这个问题并提供一个调试模式(检查模式),您可以在测试应用程序时使用它;当然,这些会产生额外的成本,不仅是 CPU 方面的,而且可能是内存方面的。

因此,是否提供检查是您自己的选择,并且可能提供它是可选的。我建议开始时不要检查,稍后再添加,因为您对系统的外观有更好的了解。

于 2013-06-04T11:50:44.437 回答
1

据我了解,std 随机访问迭代器允许你超过数组。

不完全的; 您无法访问容器外部的任何内容,并且尝试这样做会产生未定义的行为。但是不需要迭代器来防止您尝试访问无效内存。

原因是检查范围可能会产生很大的运行时成本。通过不需要这个,您可以选择需要您正确设计访问模式的快速实现,或者可以为您检测一些错误的慢速、更安全的实现。

它是否允许获取它持有的超过 Size 的值?它是否允许用户覆盖该内存?

它可能会检测到并报告错误;或者它可能不会,并允许您访问具有未定义结果的无效内存。

对于我的实现,我应该允许访问大小吗?

不,允许它是没有意义的。您可以选择是通过在运行时检查访问来主动阻止它,还是通过记录用户有责任确保迭代器保持有效来被动地阻止它。

在这种情况下,什么被认为是好的编程?

未经检查的迭代器更简单,并且不会增加任何可能不需要的性能成本。您也可以提供已检查的迭代器;单独或作为未经检查的包装器,让用户选择他们想要的速度或安全性。

于 2013-06-04T11:58:07.930 回答