不返回的

Version >= C++ 11

C++ 11 引入了 [[noreturn]] 属性。它可以用于一个函数,通过执行一个 return 语句来指示函数没有返回给调用者,或者如果它是正文则通过到达结尾(重要的是要注意这不适用于 void 函数,因为它们回到调用者,他们只是不返​​回任何值)。这样的功能可以通过调用 std::terminatestd::exit 或通过抛出异常来结束。值得注意的是,这样的函数可以通过执行 longjmp 返回。

例如,下面的函数将始终抛出异常或调用 std::terminate,因此它是 [[noreturn]] 的一个很好的候选者:

[[noreturn]] void ownAssertFailureHandler(std::string message) {
    std::cerr << message << std::endl;
    if (THROW_EXCEPTION_ON_ASSERT)
        throw AssertException(std::move(message));
    std::terminate();
}

这种功能允许编译器在没有 return 语句的情况下结束函数,如果它知道代码永远不会被执行的话。这里,因为在下面的代码中对 ownAssertFailureHandler(上面定义)的调用永远不会返回,所以编译器不需要在该调用下面添加代码:

std::vector<int> createSequence(int end) {
    if (end > 0) {
        std::vector<int> sequence;
        sequence.reserve(end+1);
        for (int i = 0; i <= end; ++i)
            sequence.push_back(i);
        return sequence;
    }
    ownAssertFailureHandler("Negative number passed to createSequence()"s);
    // return std::vector<int>{}; //< Not needed because of [[noreturn]]
}

如果函数实际返回,则是未定义的行为,因此不允许以下内容:

[[noreturn]] void assertPositive(int number) {
    if (number >= 0)
        return;
    else
        ownAssertFailureHandler("Positive number expected"s); //< [[noreturn]]
}

请注意,[[noreturn]] 主要用于 void 函数。但是,这不是必需的,允许在泛型编程中使用这些函数:

template<class InconsistencyHandler>
double fortyTwoDivideBy(int i) {
    if (i == 0)
         i = InconsistencyHandler::correct(i);
    return 42. / i;
}

struct InconsistencyThrower {
    static [[noreturn]] int correct(int i) { ownAssertFailureHandler("Unknown inconsistency"s); }
}

struct InconsistencyChangeToOne {
    static int correct(int i) { return 1; }
}

double fortyTwo = fortyTwoDivideBy<InconsistencyChangeToOne>(0);
double unreachable = fortyTwoDivideBy<InconsistencyThrower>(0);

以下标准库函数具有以下属性:

  • std ::中止
  • std ::退出
  • std::quick_exit
  • std ::意外
  • std ::终止
  • std::rethrow_exception
  • std::throw_with_nested
  • std::nested_exception::rethrow_nested