是否有必要在 std::coroutine_handle 上调用 destroy?

Is it necessary to call destroy on a std::coroutine_handle?

std::coroutine_handle是C++20新协程的重要组成部分。例如,生成器经常(总是?)使用它。在我看到的所有例子中,句柄都是在协程的析构函数中手动销毁的:

struct Generator {
    // Other stuff...
    std::coroutine_handle<promise_type> ch;

    ~Generator() {
        if (ch) ch.destroy();
    }
}

这真的有必要吗?如果是,为什么 coroutine_handle 还没有完成,是否有 coroutine_handle 的 RAII 版本以这种方式运行,如果我们省略 destroy 调用会发生什么?

示例:

  1. https://en.cppreference.com/w/cpp/coroutine/coroutine_handle (Thanks 463035818_is_not_a_number)
  2. C++20 标准在 9.5.4.10 示例 2 中也提到了它(在 N4892 上检查过)。
  3. (德语)https://www.heise.de/developer/artikel/Ein-unendlicher-Datenstrom-dank-Coroutinen-in-C-20-5991142.html
  4. https://www.scs.stanford.edu/~dm/blog/c++-coroutines.html - 提到如果不调用它会泄漏,但没有引用标准中的段落或为什么不在 std::coroutine_handle 的析构函数中调用它。

这是因为您希望协同程序的寿命超过其句柄,句柄应该非拥有。句柄只是一个“视图”,很像 std::string_view -> std::string。如果 std::string_view 超出范围,您不希望 std::string 自行销毁。

如果您确实想要这种行为,围绕它创建自己的包装器将是微不足道的。

也就是说,标准 specifies:

The coroutine state is destroyed when control flows off the end of the coroutine or the destroy member function ([coroutine.handle.resumption]) of a coroutine handle ([coroutine.handle]) that refers to the coroutine is invoked.

协程状态将在完成后自行清理运行,因此它不会泄漏,除非控制没有从末端流出。

当然,在生成器的情况下,控制通常不会从末尾流出,因此程序员必须手动销毁协程。协程有多种用途,因此标准不能真正无条件地强制执行句柄析构函数调用 destroy().