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

Bro*_*her 12 c++ coroutine c++20

std::coroutine_handle是C ++ 20的新协程的一个重要部分。例如,发电机经常(总是?)使用它。在我见过的所有示例中,在协程的析构函数中手动销毁句柄:

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

    ~Generator() {
        if (ch) ch.destroy();
    }
}
Run Code Online (Sandbox Code Playgroud)

这真的有必要吗?如果是的话,为什么没有这个已经被完成的coroutine_handle,是有一个RAII版本coroutine_handle,其行为这种方式,并会如果我们忽略了发生什么destroy电话?

例子:

  1. https://en.cppreference.com/w/cpp/coroutine/coroutine_handle(感谢 463035818_is_not_a_number
  2. C++20 标准也在 9.5.4.10 Example 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

Som*_*ken 7

这是因为您希望能够让协程比其句柄寿命更长,句柄应该是non-owning。句柄只是一个“视图”,很像std::string_view -> std::string. std::string如果std::string_view超出范围,您不希望自行破坏。

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

话虽如此,该标准规定

当控制从协程的末尾流出引用协程的协程句柄 的destroy成员函数 被调用时,协程状态将被破坏。([coroutine.handle.resumption])([coroutine.handle])

协程状态会在运行结束后自行清理,因此不会泄漏,除非控制权没有从最后流出。

当然,在生成器的情况下,控制通常不会流到最后,因此程序员必须手动销毁协程。协程虽然有多种用途,因此标准不能真正无条件地要求句柄析构函数调用destroy()