协程和带有静态变量的函数有什么区别?

10

我正在学习C++20的新内容,试图理解常见的co-routines生成器用例。我在这里尝试创建一个小例子,但如果有错误,请原谅:

generator<int> Generate() {
    int i = 0;
    while(1) {
        co_yield i++;
    }
}

int main()
{
    auto gen { Generate() };
    for (int x = 0; x < 10; ++x) {
        gen.next();
        std::cout << gen.getValue() << std::endl;
    }
    return 0;
}

但我不认为这与带有静态变量的函数有任何区别,例如:

auto gen() {
    static int i = 0;
    return i++;
}

int main()
{
    for (int x = 0; x < 10; ++x)
        std::cout << gen() << std::endl;
    return 0;
}

我认为我可能能够看到异步I/O是一个使用案例,特别是对于co_await关键字,但对于这个生成器示例,我肯定对它们的使用方式存在误解。如有任何解释,将不胜感激。

1个回答

14

最显然的区别可能是,static局部变量意味着你实际上只有一个实例... 总共。而每个生成器都是完全独立的。

// with coroutines
assert(Generator().next() == 0);
assert(Generator().next() == 0);
assert(Generator().next() == 0);
assert(Generator().next() == 0);

每次调用Generator()都会创建一个新的生成器,每个生成器都从0开始计数。因此,每个新生成器的next()都会给我零。正如预期的那样。

但对于静态局部变量,情况并非如此:

assert(gen() == 0);
assert(gen() == 1);
assert(gen() == 2);
assert(gen() == 3);

因此,你可以想象一下,如果你想创建一个产生无限整数流的生成器,那么在整个程序中可靠地多次使用该函数将是很好的。

这并不是说静态局部变量没有用处。只是它们不能用于这种特定的用例。


啊哈!这是我完全没有考虑过的事情。非常好的答案,非常感谢。 - rbv
5
另一方面,Lambda 表达式 [i = 0]() mutable -> int { return ++i; }。 (注:Lambda 表达式是 C++11 引入的一种匿名函数,该表达式可以在需要函数对象时定义并使用,通常用于函数回调、STL 算法等场景。在这个例子中,[i = 0] 是捕获列表,() mutable 是参数列表和可变说明符,-> int 是返回类型说明符,{ return ++i; } 是函数体。) - Eljay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接