Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ “的例外政策”;最后";在C++;_C++_Exception Handling_Raii_Finally - Fatal编程技术网

C++ “的例外政策”;最后";在C++;

C++ “的例外政策”;最后";在C++;,c++,exception-handling,raii,finally,C++,Exception Handling,Raii,Finally,最后考虑类,,在析构函数中运行任意用户代码 以下是最简单的实现(无转发、辅助功能等): 模板 终于上课了 { 公众: 最后(Func f):f_f(f){} ~finally(){f_u();} 私人: Func f_; }; 问题是:应该如何处理用户代码中的异常 这里是我可以想到的变体,假设该类应该在广泛的情况下使用,您认为哪一个更好 1)什么也不做~finally()/*noexcept*/{f_u();} 的析构函数finally是隐式的noexcept,因此用户代码中的任何异常都会导致

最后考虑类
,在析构函数中运行任意用户代码

以下是最简单的实现(无转发、辅助功能等):

模板
终于上课了
{
公众:
最后(Func f):f_f(f){}
~finally(){f_u();}
私人:
Func f_;
};
问题是:应该如何处理用户代码中的异常

这里是我可以想到的变体,假设该类应该在广泛的情况下使用,您认为哪一个更好

1)什么也不做<代码>~finally()/*noexcept*/{f_u();}

的析构函数finally
是隐式的
noexcept
,因此用户代码中的任何异常都会导致
terminate()
。 用户每次都必须考虑代码的正常性,并在抛出时使用try/catch手动保护代码

2)完全透明的析构函数<代码>~finally()无例外(f_()){f_();}

finally
的析构函数是有条件的
noexcept
,因此任何异常都会被传递,并且只有在堆栈展开期间发生时才会调用
terminate()
。 用户可能应该考虑堆栈展开场景,但默认情况下,在这种情况下调用
terminate()
可能是正确的决定

3)捕获析构函数中的所有异常
~finally(){try{f_u()}catch(…){}

经典的析构函数没有抛出任何东西。 限制用户在异常情况下进行错误检查的能力,但出于善意。可能因为try/catch阻塞而效率较低。用户不必考虑任何事情

3+(可能)优化了3),如果
f_389;(
noexcept
,则使用专门化/SFINAE省略try/catch块

可能会在try/catch块中冗余地包含C函数,如
fclose(FILE*)
,因为它们不是noexcept,但此类函数可能不会直接与finally一起使用,而是通过lambda使用,出于遗忘的原因,lambda也很容易不被标记为
noexcept

4)静态断言,即
f_()
不例外

用户每次都必须显式地将其代码标记为
noexcept
,然后捕获或不捕获异常是他关心的问题。再次限制用户对异常进行错误检查的能力,但出于善意


4+4)加上finally的一些特殊化(可能是另一个单独的类模板),语义为2),它没有断言,但必须显式使用。

RAII应该对这个
finally
的任何用途负责。它不是最小的,因为它违反了三个规则。没有人会在代码评审中使用非r3代码,对吗?@Plasmah但是正在被
最终清理的对象应该在其析构函数中清理自己。似乎您正在尝试重新实现范围退出库您应该看看@R.Martinho Fernandes。我省略了已删除的复制构造函数/赋值(ust与其他所有内容一样),因为它们与问题无关。这并不是一个真正有用的类,只是一个问题的说明。
template<typename Func>
class finally
{
public:
    finally(Func f) : f_(f) {}
    ~finally() { f_(); }

private:
    Func f_;
};