Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.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++_Language Lawyer_Noexcept - Fatal编程技术网

C++ 无例外和可靠性保证

C++ 无例外和可靠性保证,c++,language-lawyer,noexcept,C++,Language Lawyer,Noexcept,最近,我试图回答我认为是关于noexcept异常规范的问题。最终的结果是,我发现我对noexcept的基本理解是错误的 在阅读以纠正误解的过程中,我发现自己问了一些关于noexcept的问题,但没有得到回答 noexcept是否应被视为安全保证,即调用函数时不仅不会抛出,而且不会损坏状态 假设(1.)为false:使用noexcept作为可移植程序来终止应用程序而不进行清理以防止保存状态损坏是否正确 对(2.)的澄清:目的只是防止析构函数从noexcept向上调用堆栈,而不是防止在堆栈中展开。这

最近,我试图回答我认为是关于
noexcept
异常规范的问题。最终的结果是,我发现我对
noexcept
的基本理解是错误的

在阅读以纠正误解的过程中,我发现自己问了一些关于
noexcept
的问题,但没有得到回答

  • noexcept
    是否应被视为安全保证,即调用函数时不仅不会抛出,而且不会损坏状态
  • 假设(1.)为false:使用
    noexcept
    作为可移植程序来终止应用程序而不进行清理以防止保存状态损坏是否正确
  • 对(2.)的澄清:目的只是防止析构函数从
    noexcept
    向上调用堆栈,而不是防止在堆栈中展开。这是基于这样一个假设,即这是一个完美的RAII环境,堆栈上的析构函数可能会清除全局状态以实现持久性,从而破坏它

    如何不进行退绕的示例:

    #include <iostream>
    #include <exception>
    
    namespace{
       struct foo{
           void change_state() noexcept
           {
              // change state and fail
              throw std::exception();
           }
           ~foo(){
              std::cout << "Destructor called, saved state corrupted!" <<std::endl;
           }
        };
    }
    
    
    int main(){
        ::std::set_terminate([](){
            std::cout<< "Terminate called" <<std::endl;
        });
    
        foo f;
        f.change_state();
        return 0;
    }
    
    #包括
    #包括
    名称空间{
    结构foo{
    void change_state()无异常
    {
    //改变状态并失败
    抛出std::exception();
    }
    ~foo(){
    标准::cout
    
  • 是的。函数不应该损坏状态、句点,不管它是否抛出。它可能想要抛出异常的事实无关紧要。[当然,不能保证它不会使程序崩溃。不过,这种行为可能应该记录在案。;-]
  • 如果一个函数希望抛出一个
    noexcept
    ,它不应该费心抛出;它应该只调用
    std::terminate
    (或者
    std::abort

  • noexcept
    是一种合同担保,非常类似于
    assert
    无法关闭。如果标记为
    noexcept的函数
    尝试通过异常退出,已禁用post条件
    违反了,你不能指望任何东西;程序将
    终止。因此,1为假

    至于2,则更为困难。实施可能会 展开堆栈,直到它尝试使用
    noexcept
    ;它是否可能(至少对我来说)不是100%清楚 不要进一步展开堆栈。如果要终止 没有清理的应用程序,然后我将调用
    abort()
    ,这是 保证在不采取任何进一步行动的情况下立即退出 也会准确地告诉读者发生了什么,而不是
    指望一个不同功能的副作用。

    据我所知,
    noexcept
    :即使这个东西抛出,我也不想知道。所以它对“安全性”或“正确性”都不起作用,它的工作原理是防止抛出异常,这样您的程序就不会因此而结束。如果异常到达标记为
    noexcept
    的函数的最外层块,则调用
    std::terminate
    。它根本不抑制异常。它提供了一个屏障,异常可能不会通过我所写的异常e before是关于运行时的,
    noexcept
    在编译时工作,因此它是对编译器的一个提示,编译器会评估您的程序,如果有可能抛出一些东西,您有机会在运行前更正它,因为
    noexcept
    操作符在编译时会失败。它的工作方式类似于
    类型特征
    在某些情况下,您定义了一个需要计算为
    true
    的属性,如果没有,编译器会警告您,如果测试通过,您知道在运行时您将拥有在
    traits
    条件中定义的类型。对于
    noexcept
    ,情况也是如此。我认为没有理由相信1)(函数总是会破坏状态,即使没有例外),但我想说2)是正确的。@user2485710我认为您不理解上面问题中的链接标准。这绝对不是
    noexcept
    所做的。有一个标记为
    noexcept
    的函数,其中包含
    throw
    语句,甚至不
    catch
    语句是完全合法的援助抛出。然而,这样做的结果将是调用
    std::terminate
    。我理解你的意思,这种失败应该是明确的,而不是依赖于
    noexcept
    的行为。我想我是在戳理论,当标记为
    noexcept
    的函数调用抛出的函数时。你是否捕捉到exception,然后调用
    std::terminate
    ?呃……如果外部函数捕获和处理异常是有用的,那么它当然应该这样做。之后,它可能应该调用
    terminate
    ,以证明它不必费心维护类不变量。
    throw
    的一个意思是“但别担心,我们没事。”这么说,如果
    抛出
    距离
    noexcept
    有一英寸的屏幕空间,这没什么大不了的。因此,在这种特殊情况下,你会用
    捕获
    ”来包装任何不安全的(非
    noexcept
    )调用,然后调用
    std::abort
    ,以防止进一步解除?(我假设在
    noexcept
    函数中展开不会损坏保存的状态)@Mgetz正常情况下,我不会进行任何不安全的调用:-)。否则,如果我想吞下它们,我只会包装它们(例如,通常是在堆栈展开期间调用析构函数的情况)。我的问题似乎不太清楚……其目的只是为了防止析构函数调用比
    noexcept
    更高的堆栈级别。但如果我理解你的意思……你的意思是,在全局保存状态可能损坏的情况下,最好像在
    noexcept
    上下文中那样操作,然后只是
    中止
    If立即需要。@Mgetz当您检测到错误时