`noexcept`关键字的正确用法及函数标注合理性问询
noexcept属性的使用疑问 我正试图弄清noexcept属性的正确用法,已花费半天时间学习但仍不确定,不想盲目地到处使用或不使用它。
问题: 我的理解是否正确——若一个函数仅调用带有noexcept属性的函数,那么我们可以(或应该)安全地将该函数也标记为noexcept?
假设我有用于检查指定路径是否存在且为目录的函数,使用filesystem库实现。其中函数IsDir调用未标记noexcept的exists和is_directory函数;另一个函数IsDir2调用标记了noexcept的exists和is_directory函数。我能否安全地将第二个函数标记为noexcept?
#include <iostream> #include <filesystem> namespace fs = std::filesystem; bool IsDir(const fs::path& p) { const bool exists{ fs::exists(p) }; // 未标记 "noexcept" const bool is_dir{ fs::is_directory(p) }; // 未标记 "noexcept" return exists && is_dir; } bool IsDir2(const fs::path& p, std::error_code& ec) noexcept { const bool exists{ fs::exists(p, ec) }; // "noexcept" 版本 const bool is_dir{ fs::is_directory(p, ec) }; // "noexcept" 版本 return exists && is_dir; } int main () { const fs::path p("~/Some_Path"); std::cout << std::boolalpha << IsDir(p) << std::endl; std::error_code ec; std::cout << IsDir2(p, ec) << std::endl; return 0; }
你的理解大体正确,但需要明确几个关键细节:
核心前提:确认调用的函数确实不会抛异常
你调用的带error_code参数的fs::exists和fs::is_directory是标准库明确标记为noexcept的版本——这类函数会将错误信息写入传入的error_code对象,而非抛出异常。只要这些函数的行为符合标准承诺,IsDir2内部就不会产生未被捕获的异常,标记noexcept是安全的。noexcept是一种承诺而非自动推导
给函数加noexcept,相当于向编译器和调用者保证:这个函数不会抛出异常。只要你能确保函数内部所有执行路径(包括调用的外部函数、自身逻辑)都不会触发异常,就可以标记。如果违反这个承诺(比如内部调用了可能抛异常的函数却未处理),程序会直接调用std::terminate终止,风险很高。自身逻辑也需排查异常风险
除了外部调用,还要检查自己的代码是否有抛异常的可能。比如IsDir2里只有简单的布尔运算和变量赋值,这些操作都不会触发异常,所以没问题。如果函数里包含new操作、可能越界的容器访问等逻辑,哪怕调用的外部函数是noexcept,自身逻辑也可能抛异常,这时候就不能标记noexcept。
回到你的代码:IsDir2完全满足条件,标记noexcept是安全且合理的。而IsDir调用的无error_code版本会在出错时抛出std::filesystem::filesystem_error,绝对不能给它加noexcept。
内容的提问来源于stack exchange,提问作者ENIAC

