【问题标题】:Easiest way to terminate function in C++在 C++ 中终止函数的最简单方法
【发布时间】:2013-12-14 21:56:41
【问题描述】:

我想知道在 C++ 中终止函数最简单或最方便的方法是什么。

例如我有int function(),我希望它在函数中的某些条件下什么都不做(有点像void),但我不希望整个程序终止。所以,请不要“退出”:D。

我看到人们使用return;,但我不确定它是否安全。

希望你能帮助我。谢谢!

【问题讨论】:

    标签: c++ error-handling terminate


    【解决方案1】:

    是的,return 你能回来吗?

    或者您可以throw 例外。

    在这两种情况下,您都需要注意处理所需的资源释放。

    【讨论】:

    • 资源释放应该始终由析构函数处理,因此无论流量如何,它们都会保证发生。
    • @Potatoswatter 在 C++ 中并不总是这样,只有局部变量会被自动销毁。
    • @Potatoswatter 这几乎听起来像“不要担心资源”,我更愿意建议“始终使用 RAII 分配/释放资源,以便通过返回离开函数是安全的或例外”。
    • @polkadotcadaver RAII 与使用析构函数解除分配相同。
    • @PeterHorvath 然后用适当的析构函数声明一个新类型的本地对象。
    【解决方案2】:

    您需要提供返回值或throw 异常。如果控制流正常返回给调用者,那么只需return 0;。但这表明存在组织问题。

    只有返回void的函数才允许没有值的return

    【讨论】:

      【解决方案3】:

      在声明为 int function() 的函数中,您始终可以返回一些值,例如使用return 0; - 在函数体内的任何时间和任何地方。

      你也可以通过抛出一个exception 离开一个函数,这是一个非本地的control flow 转移。

      在实践中,您会抛出一些异常,例如

       throw std::runtime_error("something bad");
      

      那么call stack 中的某些功能仍然处于活动状态应该catch 那个异常。所以也许你的main 包含

       try {
          do_the_job(something);
       } 
       catch (std::runtime_error err) {
          std::cerr << "bad thing happened:" << err.what() << std::endl;
          exit(EXIT_FAILURE);
       }
      

      do_the_job 调用foo 调用bar 调用你的function 哪个throwmain 中捕获的异常等等......(调用堆栈上的局部值的析构函数被调用)。

      【讨论】:

        【解决方案4】:

        在 C++ 中有 3 种方法可以结束函数:

        • return一个合适的值
        • throw 异常
        • std::terminate程序

        这取决于你,程序员,来决定如何处理你所处的情况。一般来说,你会发现自己处于两种情况:

        • 技术错误:损坏状态,违反先决条件,通常通过调用std::terminatethrow 处理
        • 功能情况:给定参数,没有结果(例如search可能失败),一般通过调用throw或返回一个标记值来处理。

        因此,由于在您的情况下,我们似乎在谈论一种功能情况,您可能会问自己,这种情况是否是调用者方面的错误(在这种情况下,异常是一个好的候选人)或者如果这是正常情况(例如search没有找到任何东西),在这种情况下,哨兵值可能是最好的。

        对于哨兵值,我见过一些方法:

        • C-ish:返回一个指针(并使用nullptr 作为 Sentinel),如果需要,可以是一个智能指针
        • Object-ish:有一个这样的 Null 对象
        • 愚蠢的布尔:通过引用获取“返回参数”并返回一个布尔值以指示您是否写入它
        • Functional-ish:返回 boost::optional&lt;Type&gt;(并使用 boost::none 作为 Sentinel)

        确实有很多方案可供选择;如果你返回一个副本,我会推荐后者,如果你返回一个预先存在的对象的句柄,我会推荐后者。

        【讨论】:

        • +1,可能还会注意到 terminate 适用于违反析构函数的先决条件的情况。
        【解决方案5】:

        如果你的函数有返回类型int,那么如果你返回,你需要返回一个值,而不仅仅是return;

        你的函数的返回值可能对调用者有一些意义。因此适用以下三种情况之一:

        1) 有一些可用的整数值并不意味着“我做了某事”。因此,您可以记录该值意味着“我什么都没做”,然后返回。 0-1 通常是最有可能用于此目的的值,但这完全取决于函数的作用和返回值的含义。

        2) 没有可用的值不代表“我做了某事”,因此该函数无法返回一个值来表示“我什么也没做”。然后,您可以更改函数的签名,为其提供一种指示它是否执行任何操作的方法——例如,返回一个 pair&lt;bool,int&gt; 而不仅仅是一个 int,其中一个值表示成功/失败,另一个值表示有意义关于成功而不是失败。或者,您可以将int &amp; 参数添加到function,您将在其中存储当前用作返回值的值,并将返回类型更改为bool,它仅指示成功或失败。或者,如果所讨论的情况是函数无法执行其设计的操作,那么您可以抛出异常(并记录函数可能抛出的内容)。

        在上述两种情况下,调用该函数的现有代码可能必须更新(如果您更改签名肯定会更新)。这就导致了第三种情况:

        3) 函数没有办法表明它什么也没做,并且你不能改变函数的接口(例如,也许它已经记录了不抛出而你不想改变现有调用者依赖的事实)。那我恐怕你处于你不想要的境地。如果一个函数发现即使通过抛出它也无法履行其合同义务,那么你所能做的就是terminateexit。程序无法继续,因为调用者完全有权期望该函数会做“某事”,但您不能这样做。这通常表明设计存在某种错误,或者您正在实现的接口不够灵活,无法支持您的计划。

        【讨论】:

          【解决方案6】:

          简单地使用return 可能会给您带来一些麻烦,因为编译器要求您实际返回一个值,并且任何合理的人在阅读您的原型时都会期望如此。对于您的情况,最好的方法是 throw 例外。

          编辑:下面提醒我,是的,只有在出现不可恢复的错误时才应抛出异常。也许一个简单的return 是最快的方法。但是,您应该采取的正确行为是在满足您的条件时引发某种错误标志。

          【讨论】:

          • 在 void 函数中,您不需要返回值。
          • 他确实需要返回一个整数,并且它的值应该对函数的用户有意义,但是只有在退出该方法的原因是存在一个不可恢复的错误。
          • @PeterHorvath "例如我有 int function()"
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-03-15
          • 2019-05-12
          • 2012-03-28
          • 1970-01-01
          • 2011-07-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多