为什么 std::string::substr 抛出异常而不是返回空字符串?

tgl*_*las 6 c++ string substr

一段时间以来,我一直想知道std::stringsubstr(pos, len)方法设计背后的基本原理。这对我来说仍然没有意义,所以我决定请教专家。std::out_of_range如果pos参数超过字符串长度加一,该函数将引发异常。这有时会很不方便(甚至很烦人),但我真正关心的是一致性和最小惊喜原则。事实证明,pos+len子串的“结束”位置允许超过字符串长度加一。一开始就不允许这样做,但在结束时不允许这样做,这对我来说是不一致的。允许它结束我暗示了解释

返回位置处的所有字符 pos <= i < pos+len

但是,那么我希望该函数为pos超过字符串长度的值返回一个空字符串,而不是抛出异常。作为旁注,根据这种解释,允许负值甚至是明智的pos(假设它具有有符号类型)。

这给我留下了以下问题:

  • 你觉得这个设计合乎逻辑吗?明智吗?您是否有令人满意的方法来解决不一致的问题?我能想出的唯一可能的解释是与空终止字符串的兼容性。对于空终止,指定的长度是否超过结尾无关紧要,而超出空字符的开始是内存错误。然而,std::string不是空值终止,而是跟踪字符串的长度。如果这是真正的原因,那么我个人认为这是一个非常糟糕的原因。
  • 在性能方面有优势吗?我真的会很惊讶。
  • 我是否忽略了可用性方面的优势?也许一个标准的习惯用法或用例与其他函数结合使用,比如 find?同样在这里我的印象是返回一个空字符串有可能简化一些代码。
  • 有没有办法改变substr未来的行为?我想不会,因为默默地破坏现有代码肯定比忍受这种扭曲更糟糕......?

Ter*_*ein 3

这个问题确实太主观了,但我会尽力逐条回答。

  • 这个设计对你来说合乎逻辑吗?明智吗?对我来说这似乎合乎逻辑。也许这样的意见来自strncmp-styled 函数,但是通过这样的设计,您只需传递len参数的缓冲区长度即可正常工作。但是,如果您尝试访问位于字符串边界之外的子字符串,那么您可能错过了一些简单的健全性检查。和内部实施std::string无关紧要。
  • 性能方面有优势吗?我认为这不是原因。
  • 我是否忽略了可用性方面的优势?也许,看看第 1 点。
  • 将来有什么办法可以改变 substr 的行为吗?pos标准中定义了超出范围时抛出异常size(),因此很可能不会。

我的观点是:这个异常(尽管我宁愿永远不使用它们)允许您注意到缺少一些基本健全性检查的代码,例如访问其边界之外的缓冲区。相同的设计用于at()类似功能和许多其他功能。