C++ 从不将涉及动态内存分配的函数注释为noexcept?

C++ 从不将涉及动态内存分配的函数注释为noexcept?,c++,c++11,bad-alloc,noexcept,C++,C++11,Bad Alloc,Noexcept,假设您有一个通常不会失败的功能,例如: std::string convert_integer_to_string(int x); 在pricipal中,这将是noexcept的候选项。然而,实现很可能涉及到动态内存管理,因此在使用new操作符分配内存时,它可能总是抛出一个错误 是否建议将函数注释为noexcept? 从实践的角度来看,以合理的方式处理内存不足的情况是极其困难的。大多数程序只是假设有足够的可用内存。调用std::terminate,在这种情况下,调用noexcept函数抛出st

假设您有一个通常不会失败的功能,例如:

std::string convert_integer_to_string(int x);
在pricipal中,这将是
noexcept
的候选项。然而,实现很可能涉及到动态内存管理,因此在使用
new
操作符分配内存时,它可能总是抛出一个错误

是否建议将函数注释为noexcept?

从实践的角度来看,以合理的方式处理内存不足的情况是极其困难的。大多数程序只是假设有足够的可用内存。调用
std::terminate
,在这种情况下,调用
noexcept
函数抛出
std::bad_alloc
似乎是合理的

对我来说,
noexcept
是某种形式的文档。您(或优化器)可以安全地假设此函数永远不会抛出。如果您正在编写一个不关心内存不足情况的应用程序,这仍然是一个有效的假设


我想最安全的建议是,如果可能引发
std::bad_alloc
异常,则永远不要使用
noexcept
。另一方面,我想知道使用
noexcept
是否有好处,假设您不关心内存不足的情况(即,如果
std::terminate
正常)。

如果函数可以出于任何原因抛出异常,即使它是
std::bad\u alloc
,您应该将其声明为
noexcept
。相对而言,很少有函数真的不能抛出异常,而且它实际上在哪里也很重要。
noexcept
函数的主要需求是允许在异常情况下检测可用的错误恢复选项:例如,
std::vector
可以在插入对象时使用移动构造,前提是移动构造不会抛出。如果移动构造可以抛出,则在实现强异常安全操作时,不能使用移动对象来恢复异常。因此,如果类型
T
的移动构造失败,
std::vector
的实例化无法移动对象,但需要复制它们


特别是,不要将
noexcept
用作虚假文档:如果函数实际上可以抛出,则属于违约。在这种情况下,系统会以某种程度的已定义行为做出反应,这一事实并不意味着你应该利用它。。。虽然简单的程序可能无法恢复,在内存不足时会死掉,但真正的程序可能至少需要存储足够的状态来恢复死掉时留下的混乱,也就是说,任何函数都不能做出终止程序的决定(当然,除非记录了该函数的意图).

我不确定我会不会太担心内存不足异常

在某些操作系统(至少是linux)下,内存耗尽时的默认行为是由操作系统(通过)终止。当您写入内存(而不是分配内存)时,就会发生这种情况,您将没有机会运行任何清理代码。此功能称为

即使您得到了内存耗尽的信息,也很难正确处理这些错误:您需要绝对确保异常处理程序不分配内存。这包括来自该错误处理程序的所有函数,您还需要确保任何可能在此过程中触发的通用异常处理程序(例如日志记录)不使用任何内存。您通常希望的最好结果是在关闭程序之前进行一些简单的清理


请注意,您还可以使用检查分配结果而不使用异常(即,在分配时提供操作系统实际上会告诉您该信息)。当您进行一个您认为可能失败的大型分配时,这样做可能是有意义的。它还有一个很好的特性,即不处理(可能)未捕获的异常,您将得到一个非常容易调试的nullptr。

您的示例函数可能会更好,因为
std::to_string
@chris Yes,这只是我编的一个例子。相关:+1我认为任何函数都不能接受决定终止程序是关键。