c++yieldyield

OKX欧意app

欧意交易app是全球排名第一的虚拟货币交易所。

APP下载   官网地址

摘要:本文将详细阐述C++中的yield关键字,探讨其如何在代码中实现协程和生成器等功能。首先,我们将介绍yield的基本概念,然后讨论其与协程的关系,接着将深入探讨如何使用yield实现生成器和状态机,最后对全文进行总结归纳。

1、yield基本概念

yield关键字是C++11中新增的一个关键字,其作用是将当前函数的执行权返回给调用者,同时保存当前函数的所有状态。当然,调用者必须也是一个可以暂停执行的函数,否则就没有继续执行的机会了。

yield的具体语法如下:

T yield<T>(Args... args);

其中T表示返回值类型,而Args表示函数参数列表,yield的返回值类型和参数类型根据具体情况而定。

2、yield与协程

协程是指一种可以在函数中暂停执行、保存当前状态,然后在需要的时候恢复执行的机制。通过协程,我们可以在一个函数中实现多个逻辑流程,提高代码的可读性和可维护性。

在C++中,yield关键字可以用来实现协程。我们可以使用yield将当前函数的执行权交给外部调用者,然后保存当前函数的所有状态,当再次需要执行时,恢复函数的状态,继续执行。

c++yieldyield插图

在执行流程上,协程的实现和线程非常相似,但协程是由程序自己控制的,不会像线程那样被操作系统调度。这使得协程的切换速度非常快,非常适合在实现IO密集型任务时使用。

3、yield实现生成器和状态机

在C++中,我们可以使用yield实现生成器和状态机。生成器是指一种可以按照某种规则生成一组数据的工具,比如Python中的生成器。而状态机是指一种可以按照预设的状态转移规则,自动进行状态转移的程序。

基于yield,我们可以比较方便地实现这两种工具。以生成器为例,我们可以使用yield将一组数据以迭代器的形式返回给调用者:

template <typename T>

class Generator {

public:

struct Promise {

T value;

std::suspend_always yield_value(T value) {

this->value = value;

return {};

}

std::suspend_never initial_suspend() { return {}; }

std::suspend_never final_suspend() noexcept { return {}; }

Generator get_return_object() { return Generator{this}; }

void unhandled_exception() {}

};

Generator() = default;

Generator(const Generator &) = delete;

Generator &operator=(const Generator &) = delete;

Generator(Generator &&other) noexcept : coro{other.coro}, promise{other.promise} {

other.coro = nullptr;

}

Generator &operator=(Generator &&other) noexcept {

coro = other.coro;

promise = other.promise;

other.coro = nullptr;

return *this;

}

~Generator() {

if (coro) coro.destroy();

}

T operator()() {

coro.resume();

return promise.value;

}

private:

explicit Generator(Promise *promise) : promise{promise} {

coro = std::coroutine_handle::from_promise(*promise);

}

std::coroutine_handle coro{nullptr};

Promise *promise;

};

在这里,Generator是生成器类,其返回值为迭代器T。在Generator中,我们定义了Promise结构体,通过这个结构体,我们可以保存yield的返回值,以及实现initial_suspend和final_suspend等函数。在initial_suspend和final_suspend中,我们分别使用std::suspend_never返回,因为生成器不需要在协程挂起时进行任何操作。在yield_value中,我们将yield的返回值保存在value变量中,然后使用std::suspend_always返回一个协程挂起,以便调用者能够获取到yield的返回值。最后,在get_return_object中,我们返回一个Generator对象,以便调用者可以通过这个对象来迭代生成器。

类似地,我们也可以使用yield来实现状态机。例如,下面的代码中,我们定义了一个状态机类,该状态机可以按照预设的状态转移规则(使用yield定义)自动进行状态转移:

class StateMachine {

public:

void run() {

for (;;) {

switch (state) {

case 0: {

std::cout << "State 0\n";

state = co_yield '0';

break;

}

case 1: {

std::cout << "State 1\n";

state = co_yield '1';

break;

}

case 2: {

std::cout << "State 2\n";

state = co_yield '2';

break;

}

default: {

std::cout << "Unknown state\n";

return;

}

}

}

}

private:

int state{0};

};

在这里,我们定义了一个StateMachine类,该类定义了三个状态,每个状态可以通过yield返回对应的状态值,并将当前状态保存下来。当下一次调用时,根据当前状态,继续执行相应的代码。

4、总结归纳

通过本文的阐述,我们了解了在C++中,yield关键字可以用来实现协程和生成器等功能。与其他语言相比,C++中的yield的实现方式较为灵活,既可以使用预定义的yield语法实现协程,也可以通过自定义Promise结构体等手段来实现各种特定的需求。

在使用yield时需要注意的是,yield关键字只能在协程中使用,同时yield是一种单向的暂停机制,每个yield只会暂停一次,如果需要多次暂停,需要写多个yield。在使用生成器和状态机时,也需要对yield的返回值有所了解,以确保代码的正确性。

本文由捡漏网https://www.jianlow.com整理,帮助您快速了解相关知识,获取最新最全的资讯。

正文完
 

OKX欧意app

欧意交易app是全球排名第一的虚拟货币交易所。

APP下载   官网地址