gpt4 book ai didi

c++ - 如何结束C++代码

转载 作者:行者123 更新时间:2023-12-02 00:25:18 27 4
gpt4 key购买 nike

如果希望满足特定条件,我希望C++代码停止运行,但是我不确定该怎么做。因此,只要if语句为true,就可以随时终止代码,如下所示:

if (x==1)
{
kill code;
}

最佳答案

有几种方法,但是首先您需要了解为什么对象清除很重要,因此 std::exit 在C++程序员中被边缘化的原因。

RAII和堆栈展开

C++使用了一个称为RAII的习惯用法,简单来说,这意味着对象应该在构造函数中执行初始化,并在析构函数中进行清理。例如, std::ofstream 类[可以]在构造函数期间打开文件,然后用户对其执行输出操作,最后在其生命周期结束时(通常由其范围决定),调用析构函数实质上关闭了文件,并将所有写入的内容刷新到磁盘中。

如果您没有到达析构函数来刷新和关闭文件,该怎么办?谁知道!但是可能不会将原本应该写入的所有数据写入文件。

例如考虑这段代码

#include <fstream>
#include <exception>
#include <memory>

void inner_mad()
{
throw std::exception();
}

void mad()
{
auto ptr = std::make_unique<int>();
inner_mad();
}

int main()
{
std::ofstream os("file.txt");
os << "Content!!!";

int possibility = /* either 1, 2, 3 or 4 */;

if(possibility == 1)
return 0;
else if(possibility == 2)
throw std::exception();
else if(possibility == 3)
mad();
else if(possibility == 4)
exit(0);
}

每种可能性发生的事情是:
  • 可能性1: Return本质上离开了当前函数范围,因此它知道os生命周期的结束,因此通过关闭文件并将其刷新到磁盘来调用其析构函数并进行适当的清理。
  • 可能性2:引发异常还可以照顾当前范围内对象的生命周期,从而进行适当的清理...
  • 可能性3:在这里,堆栈展开起作用!即使在inner_mad处引发了异常,展开器也将通过madmain堆栈执行适当的清理操作,所有对象(包括ptros)都将被正确地销毁。
  • 可能性4:好吗? exit 是C函数,它不知道也不与C++习惯用法兼容。 不会对您的对象执行清理,包括在相同范围内的os。因此,您的文件将无法正确关闭,因此,该内容可能永远不会写入其中!
  • 其他可能性:通过执行隐式return 0并因此具有与可能性1相同的效果(即适当的清理),它将离开主要范围。

  • 但是不要对我刚才告诉你的内容那么确定(主要是可能性2和3)。继续阅读,我们将找到如何执行基于异常的适当清除。

    可能的结束方式

    从主要回来!

    您应该尽可能这样做。总是喜欢通过从main返回适当的退出状态来从程序中返回。

    程序的调用者,可能还有操作系统的调用者,可能想知道程序应该执行的操作是否成功完成。由于相同的原因,您应该返回零或 EXIT_SUCCESS 表示程序已成功终止,而返回 EXIT_FAILURE 表示程序未成功终止,任何其他形式的返回值都是实现定义的(第18.5/8节)。

    但是,您可能在调用栈中非常深入,而返回所有这些调用可能会很痛苦。

    [不要]抛出异常

    抛出异常将通过调用之前任何作用域中每个对象的析构函数,使用堆栈展开来执行适当的对象清理。

    但是这是 捕获的!它是由实现定义的,是在未处理抛出的异常(通过catch(...)子句)时,还是在调用堆栈的中间有 noexcept 函数时,是否执行堆栈展开。 §15.5.1[except.terminate]中对此进行了说明:

    1. In some situations exception handling must be abandoned for less subtle error handling techniques. [Note: These situations are:

      [...]

      when the exception handling mechanism cannot find a handler for a thrown exception (15.3), or when the search for a handler (15.3) encounters the outermost block of a function with a noexcept-specification that does not allow the exception (15.4), or [...]

      [...]

    2. 在这种情况下,将调用std::terminate()(18.8.3)。在没有找到匹配处理程序的情况下,由实现定义是否在std::terminate()被称为 [...]
    3. 之前解开堆栈


      所以我们必须捕获它!

      一定要抛出异常并捕获它!

      由于未捕获的异常可能不会执行堆栈展开(因此将无法执行适当的清理),因此我们应该在main中捕获异常,然后返回退出状态( EXIT_SUCCESS EXIT_FAILURE )。

      因此,可能的良好设置是:
      int main()
      {
      /* ... */
      try
      {
      // Insert code that will return by throwing a exception.
      }
      catch(const std::exception&) // Consider using a custom exception type for intentional
      { // throws. A good idea might be a `return_exception`.
      return EXIT_FAILURE;
      }
      /* ... */
      }

      [不要] std::exit

      这不会执行任何类型的堆栈展开操作,并且堆栈上没有 Activity 的对象将调用其各自的析构函数来执行清除。

      在§3.6.1/4 [basic.start.init]中强制执行:

      Terminating the program without leaving the current block (e.g., by calling the function std::exit(int) (18.5)) does not destroy any objects with automatic storage duration (12.4). If std::exit is called to end a program during the destruction of an object with static or thread storage duration, the program has undefined behavior.



      现在想想,你为什么要做这样的事情?您痛苦地损坏了多少物品?

      其他[坏]的选择

      还有其他终止程序的方法(崩溃除外),但不建议使用。为了澄清起见,将在此处介绍它们。请注意,正常程序终止 并不意味着意味着退出堆栈,而是使操作系统处于正常状态。
    4. std::_Exit 导致正常程序终止,仅此而已。
    5. std::quick_exit 导致正常程序终止并调用 std::at_quick_exit 处理程序,不执行其他任何清除操作。
    6. std::exit 导致正常程序终止,然后调用 std::atexit 处理程序。执行其他类型的清除,例如调用静态对象析构函数。
    7. std::abort 导致程序异常终止,不执行任何清理。如果程序以非常非常意外的方式终止,则应调用此方法。它只会通知操作系统有关异常终止的任何信息。在这种情况下,某些系统会执行核心转储。
    8. std::terminate 调用 std::terminate_handler ,默认情况下调用 std::abort

    关于c++ - 如何结束C++代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1116493/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com