标准库函数何时会引发异常?

When can the standard library functions throw exceptions?

提问人:Eternal 提问时间:5/17/2023 最后编辑:Eternal 更新时间:5/17/2023 访问量:93

问:

我很难理解标准库中的哪些函数会引发异常,如果是这样,哪些函数以及何时抛出异常。

有些函数是 ,在这种情况下,它们不会,但是如果我例如查看: https://en.cppreference.com/w/cpp/string/basic_string/operator_at,运算符还没有 页面没有说明异常(这里也一样,所以它应该与模板无关)。noexceptstd::string::operator[]()noexceptstd::basic_string

我是否可以假设如果页面上没有列出异常,则意味着该函数无法抛出(但由于某种原因未标记为)?或者这是否意味着该函数可以抛出实现定义的异常?当列出例外时,它们是唯一可以抛出的吗?noexcept

编辑:

  • 有人说我应该参考实际标准而不是 cppreference 来回答我的问题,并好心地为我提供了一个相关链接。

  • 在我的示例中,相关页面将是这个:https://eel.is/c++draft/string.access,它明确声明Throws: Nothingoperator[]()

  • 话虽如此,下面的几行是 ,它没有也没有条目,所以我的问题仍然存在front()noexceptThrows

C 异常 c++- 标准库

评论

0赞 fabian 5/17/2023
std::strlen 绝对不应该抛出异常,至少,如果使用 C 标准库的实现,但它没有说明符,因为 C 没有例外。这意味着至少在某些情况下缺少说明符,并且函数无法引发异常。noexceptnoexcept
0赞 Eternal 5/17/2023
@fabian,我在问题中链接到,但我问题的核心是关于无论实现如何,标准都能保证什么std::abs
0赞 Jesper Juhl 5/17/2023
“我可以假设如果页面上没有列出异常,那么这意味着该函数无法抛出(但由于某种原因没有被标记为no)?” - 我不认为这是一个有效的假设 - cppreference 很好,但它不是标准。此外,由于并非所有函数签名都已更新,因为添加到语言中(我几乎可以肯定他们忘记了某些函数)。顺便说一句,标记为可以抛出异常的函数,只是意味着如果它这样做,那么将被调用。noexceptnoexceptnoexceptstd::terminate
0赞 Eternal 5/17/2023
@JesperJuhl我的意思是,并不意味着不能调用,但它确实意味着没有异常可以离开函数(因为被调用)。关于标准,我不知道在不购买实际标准的情况下可以在线咨询一些东西。我会编辑我的问题noexceptthrowstd::terminate
1赞 Peter 5/17/2023
std::basic_string::operator[]()如果其参数 (index) 超出范围,则具有未定义的行为 - 这既不禁止也不需要抛出异常。事实上,在标准库的某些实现的某些调试版本中,它确实抛出了 - 这是一种允许的行为,但如果是,则隐式不允许。相比之下,如果其参数(索引)超出边界,则会进行边界检查并引发异常,因此可以避免未定义的行为,但必须进行边界检查。其他标准容器的操作类似。noexceptstd::basic_string::at()

答:

1赞 BoP 5/17/2023 #1

有时你必须在字里行间阅读。

该字符串有一个前提条件,即索引必须有效。cppreference 说道:operator[]

如果 pos > size(),则行为未定义。

未定义的行为包括引发异常。事实上,某些实现会在调试模式下引发超出范围的异常。

数学函数,如 ,最初来自 C 库。尽管 C 库没有抛出异常,但它也没有说任何函数,因此 C++ 也不兼容。std::absnoexcept

评论

0赞 Eternal 5/17/2023
这似乎是函数不被标记的合理原因(尽管实际标准说,参见我的编辑,所以可能不是),但这只能回答一半的问题:如果前提条件得到验证,是否保证函数不会抛出异常,或者没有保证?(例如,如果验证了前提条件,则是否允许实现依赖于在系统内存不足时可能引发异常的调用?noexceptThrows: Nothingnew
0赞 BoP 5/17/2023
这很复杂。前提条件不必由库验证。这种类型的要求称为授权。:-)eel.is/c++draft/structure#specifications-3
0赞 user17732522 5/17/2023
@Eternal 如果调用满足前提条件,并且规范中有子句,则不允许抛出。(如果没有这样的条款,则允许。但这并不意味着它不能使用 例如.它只需要捕获并抑制它可能引发的任何异常,以致无法到达库函数的调用方。然后,它可能必须有一个回退才能仍然满足库调用的指定行为,因此,如果在实现中使用 or 之类的东西是合理的,那么很可能就不会有子句。Throws: NothingnewnewThrows: Nothing
2赞 user17732522 5/17/2023
@Eternal我现在没有时间。答案基本上是 eel.is/c++draft/res.on.exception.handling 的释义(+被允许做任何事情,包括在违反前提条件时抛出异常,这个答案已经涵盖了)
1赞 Eternal 5/17/2023
@user17732522 这确实回答了我的问题,谢谢!如果您使用该链接和包含第 4 段的引号创建答案,我会将其设为接受的答案