协程技术问询:co_yield返回的string_view会悬空吗?
协程中co_yield临时std::string与string_view的安全性问题
我想在协程里混合使用co_yield字符串字面量与std::string,写了如下代码:
Generator<std::string_view> range(int first, const int last) { while (first < last) { char ch = first++; co_yield " | "; co_yield std::string{ch, ch, ch}; } }
我对其中std::string的生命周期存在疑问:如果立即消费返回的string_view,是否是安全的?例如以下遍历代码:
for(auto sv : range(65, 91)) std::cout << sv;
此外,我还写出了一种安全的写法:
Generator<std::string_view> range(int first, const int last) { std::string result; while (first < last) { char ch = first++; co_yield " | "; result = std::string{ch, ch, ch}; co_yield result; } }
安全性分析
- 第一种写法存在严重安全问题:
co_yield std::string{ch, ch, ch}中的临时std::string是在co_yield表达式的局部作用域创建的,协程暂停并返回string_view后,这个临时对象会立刻被销毁,其底层内存也会被释放。此时返回的string_view就成了悬垂引用,哪怕是立即消费也属于未定义行为——虽然某些环境下可能看似正常运行,但这只是偶然情况,C++标准不保证这种操作的安全性。 - 第二种写法是安全的:
std::string result是协程帧的成员变量,其生命周期与协程本身绑定,只要协程未结束,result就会持续存在。每次赋值后co_yield它的string_view,视图指向的是result的有效内存区域,不会出现悬垂问题。
内容的提问来源于stack exchange,提问作者Tom Huntington
相关产品推荐
相关产品推荐

