【发布时间】:2021-12-24 04:36:57
【问题描述】:
我对传递给 C++ 协程的参数的生命周期感到困惑。 回复a previous question,聪明人表示
参数的生命周期是 [...] 调用者范围的一部分
现在,跟进,当传递默认参数时会发生什么
generator my_coroutine(string&& s = string()) {...}
因此,如果my_coroutine 是一个普通函数,那么s 将在其整个范围内有效。但是,如果 my_coroutine 是协程,这似乎不再成立。
特别是以下协程测试的结果让我感到惊讶:
#include <iostream>
#include <coroutine>
struct Test {
int i = 3;
Test() { std::cout << "test constructed\n";}
Test(const Test&) = delete;
Test(Test&&) = delete;
~Test() { std::cout << "test destructed\n"; }
friend std::ostream& operator<<(std::ostream& os, const Test& t) { return os << t.i; }
};
template<class T>
generator<int> coro_test(T&& t = T()) {
int i = 0;
while(i++ < 3) co_yield i;
if(i == t.i) co_yield 100;
}
int main () {
auto gen = coro_test<Test>();
while(gen.is_valid()) {
std::cout << *gen << "\n";
++gen;
}
return 0;
}
结果:
test constructed
test destructed
1
2
3
PS:为了完整起见,这是我的generator:
template<class T>
struct generator {
struct promise_type;
using coro_handle = std::coroutine_handle<promise_type>;
struct promise_type {
T current_value;
auto get_return_object() { return generator{coro_handle::from_promise(*this)}; }
auto initial_suspend() const noexcept { return std::suspend_never{}; }
auto final_suspend() const noexcept { return std::suspend_always{}; }
void unhandled_exception() const { std::terminate(); }
template<class Q>
auto yield_value(Q&& value) {
current_value = std::forward<Q>(value);
return std::suspend_always{};
}
};
private:
coro_handle coro;
generator(coro_handle h): coro(h) {}
public:
bool is_valid() const { return !coro.done(); }
generator& operator++() { if(is_valid()) coro.resume(); return *this; }
T& operator*() { return coro.promise().current_value; }
const T& operator*() const { return coro.promise().current_value; }
generator(const generator&) = delete;
generator& operator=(const generator&) = delete;
~generator() { if(coro) coro.destroy(); }
};
【问题讨论】:
-
IIRC 默认参数是在调用站点实现的,所以它不会改变任何东西。从生命周期的角度来看,它们仍然存在于调用者范围内的表达式中。一旦该表达式不再有效(例如,您暂停),那么参数也不再有效。
-
"在回答上一个问题时,smart people 表示" 'Smart people' 在这些词之后还有其他词。 “聪明人”也在一个特定问题的上下文中写了这些词,而你忽略了这个问题。
标签: c++ c++20 c++-coroutine