我应该为C函数noexcept声明包装器吗?

时间:2015-11-28 03:30:23

标签: c++ c c++11 exception noexcept

假设你有一个只调用C函数的C ++函数,比如

int ClearTheBin()
{
    int result = SHEmptyRecycleBinW(
        nullptr,
        nullptr,
        SHERB_NOCONFIRMATION |
        SHERB_NOPROGRESSUI |
        SHERB_NOSOUND);

    if (SUCCEEDED(result) ||
        result == E_UNEXPECTED) // Already empty
    {
        return 0;
    }

    return result;
}

显然有zillion different things可能会对C函数的调用出错,但由于C缺少异常,因此这些错误将存储在生成的代码中。我的问题是:这些函数应该被声明为noexcept吗?即使该方法无法抛出,也可能给读者带来错误的印象"这个功能没有任何问题,我可以认为它是100%可靠的," 因为noexcept函数通常意味着什么。

您对此事的想法是什么?

2 个答案:

答案 0 :(得分:3)

  

“此功能没有任何问题,我可以认为它是100%   可靠“

我不会那么快地假设。通常,如果我看到一个标记为noexcept的函数,我倾向于寻找可以给我错误的替代方法,如布尔状态,某种全局错误检索函数,成功/失败返回值,类似那。只有缺乏这一点,并且可能面对不会产生副作用的功能,我才能做出这样的假设。

在你的情况下,你得到了整个错误代码的功能,所以很明显只要看一眼界面文档应该告诉我事情可能会出错,但noexcept告诉我这些特殊情况不会(或至少不应)以例外形式向我(来电者)报告。

应用noexcept

一般情况下,安全方面似乎不愿意使用noexcept。例如,std::string对该函数的单一介绍,现在它可以抛出,只有noexcept会将其转换为终止而不是我们可以捕获的东西。保证函数将永远不会抛出接口/设计级别是一个很难确保实际混合C ++代码的任何东西,特别是在任何随机同事可能引入的团队设置中(可能是紧缩)一天)一些随机的C ++函数调用或对象可以抛出这个函数。

无法投掷

在某些情况下,实际上很容易做出这种保证。一个例子是noexcept函数,它有自己的try/catch块,函数所做的一切都包含在其中。如果捕获到异常,请将其转换为某种错误代码并返回该异常。在这些情况下,try/catch保证函数将吞下异常并且不会将其泄漏到外部世界。这里应用noexcept变得很容易,因为函数不能抛出。

无法正确投掷

noexcept不需要太多考虑的另一个例子是在一个函数的情况下,如果抛出则应该被认为是破坏的。一个示例是一个API函数,它跨SDK的模块边界调用,旨在允许使用任何编译器构建插件。因为我们不应该跨越模块边界,特别是在这种情况下,抛出已经是UB并且不应该完成。在这种情况下,noexcept可以很容易地应用,因为函数的正确行为,按照设计,应该永远不会抛出。

如果有疑问,请将其删除。

在你的情况下,如果有疑问,我建议不予理会。使用noexcept并且无意中抛弃了函数并终止程序,你可能会犯更多错误。例外情况是,如果您能够确保此ClearTheBin函数总是仅使用C,则不会operator new(或至少只有nothrow版本),没有dynamic_casts,没有标准的库等。除非你能为现在和将来做出这种硬接口级别的保证,否则在安全方面似乎是错误的。

答案 1 :(得分:2)

noexcept从来没有打算意味着"什么都不会出错"。 noexcept只是意味着函数不会抛出C ++异常。它绝不意味着函数在某种程度上不受其他类型问题的影响,例如未定义的行为。

所以,是的,如果您的所有函数都调用C函数,那么从正式的角度来看,声明noexcept是完全合理的事情。

如果您个人希望制定自己的约定,noexcept意味着更多,例如" 100%可靠的功能" (假设这样的事情甚至存在),那么你可以自由地这样做。但这成为你自己惯例的问题,而不是语言规范。