为什么 std::string::substr 抛出异常而不是返回空字符串?
Why does std::string::substr throw an exception instead of returning an empty string?
一段时间以来,我一直在想 std::string
的 substr(pos, len)
方法设计背后的基本原理。这对我来说仍然没有意义,所以我决定请教专家。如果 pos
参数超过字符串长度加一,该函数将抛出 std::out_of_range
异常。有时这可能会带来不便(甚至烦人),但我真正关心的是一致性和最少意外原则。原来是允许子串的"end"位置pos+len
超过字符串长度加一。一开始就不允许这样做,但最后却不允许,这对我来说是不一致的。允许它结束对我的解释
return 位置 pos <= i < pos+len
的所有字符
但是,我希望函数 return 一个空字符串,值 pos
超过字符串长度,而不是抛出异常。作为旁注,根据这种解释,允许 pos
的负值甚至是明智的(前提是它具有带符号的类型)。
这给我留下了以下问题:
- 您觉得这个设计合乎逻辑吗?懂事吗?您有解决不一致问题的令人满意的方法吗?
我能想到的唯一可能的解释是与空终止字符串的兼容性。对于空终止,指定的长度是否超过结尾并不重要,而从空字符开始是内存错误。但是,
std::string
不是 空终止的,而是跟踪字符串的长度。如果那是真正的原因,那么我个人认为这是一个非常糟糕的原因。
- 在性能方面有优势吗?我真的会很惊讶。
- 我是否忽略了可用性方面的优势?也许是一个标准的习语或用例与其他功能的结合,比如查找?同样在这里,我的印象是 returning 一个空字符串有可能简化一些代码。
- 以后有什么办法可以改变
substr
的行为吗?我想不会,因为默默地破坏现有代码肯定比忍受这种扭曲更糟糕......?
这个问题真的太主观了,不过我会尽量逐条回答。
- 您觉得这个设计合乎逻辑吗?明智? 对我来说这似乎合乎逻辑。也许这样的意见来自
strncmp
风格的函数,但通过这样的设计,您只需为 len
参数传递缓冲区长度,它就可以正常工作。但是,如果您试图访问位于字符串边界之外的子字符串,那么您可能会错过一些简单的健全性检查。 std::string
的内部实现无关紧要。
- 在性能方面有优势吗?我觉得不是这个原因。
- 我是否忽略了可用性方面的优势?也许,看看第 1 点。
- 有什么方法可以改变 substr 在未来的行为吗? 在
pos
超过 size()
时抛出异常是在标准中定义的,所以大多数可能没有。
我的观点是:这个异常(尽管我宁愿从不使用它们)允许您注意到缺少一些基本健全性检查的代码,例如访问其边界之外的缓冲区。 at()
-like 函数和许多其他函数中使用了相同的设计。
一段时间以来,我一直在想 std::string
的 substr(pos, len)
方法设计背后的基本原理。这对我来说仍然没有意义,所以我决定请教专家。如果 pos
参数超过字符串长度加一,该函数将抛出 std::out_of_range
异常。有时这可能会带来不便(甚至烦人),但我真正关心的是一致性和最少意外原则。原来是允许子串的"end"位置pos+len
超过字符串长度加一。一开始就不允许这样做,但最后却不允许,这对我来说是不一致的。允许它结束对我的解释
return 位置 pos <= i < pos+len
但是,我希望函数 return 一个空字符串,值 pos
超过字符串长度,而不是抛出异常。作为旁注,根据这种解释,允许 pos
的负值甚至是明智的(前提是它具有带符号的类型)。
这给我留下了以下问题:
- 您觉得这个设计合乎逻辑吗?懂事吗?您有解决不一致问题的令人满意的方法吗?
我能想到的唯一可能的解释是与空终止字符串的兼容性。对于空终止,指定的长度是否超过结尾并不重要,而从空字符开始是内存错误。但是,
std::string
不是 空终止的,而是跟踪字符串的长度。如果那是真正的原因,那么我个人认为这是一个非常糟糕的原因。 - 在性能方面有优势吗?我真的会很惊讶。
- 我是否忽略了可用性方面的优势?也许是一个标准的习语或用例与其他功能的结合,比如查找?同样在这里,我的印象是 returning 一个空字符串有可能简化一些代码。
- 以后有什么办法可以改变
substr
的行为吗?我想不会,因为默默地破坏现有代码肯定比忍受这种扭曲更糟糕......?
这个问题真的太主观了,不过我会尽量逐条回答。
- 您觉得这个设计合乎逻辑吗?明智? 对我来说这似乎合乎逻辑。也许这样的意见来自
strncmp
风格的函数,但通过这样的设计,您只需为len
参数传递缓冲区长度,它就可以正常工作。但是,如果您试图访问位于字符串边界之外的子字符串,那么您可能会错过一些简单的健全性检查。std::string
的内部实现无关紧要。 - 在性能方面有优势吗?我觉得不是这个原因。
- 我是否忽略了可用性方面的优势?也许,看看第 1 点。
- 有什么方法可以改变 substr 在未来的行为吗? 在
pos
超过size()
时抛出异常是在标准中定义的,所以大多数可能没有。
我的观点是:这个异常(尽管我宁愿从不使用它们)允许您注意到缺少一些基本健全性检查的代码,例如访问其边界之外的缓冲区。 at()
-like 函数和许多其他函数中使用了相同的设计。