C++并发之协程实例(二)(计算斐波那契序列)

2024-06-21 16:44

本文主要是介绍C++并发之协程实例(二)(计算斐波那契序列),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 1 协程
  • 2 实例-计算斐波那契序列
    • 2.1 斐波那契序列
    • 2.2 代码
  • 3 运行

1 协程

  协程(Coroutines)是一个可以挂起执行以便稍后恢复的函数。协程是无堆栈的:它们通过返回到调用方来暂停执行,并且恢复执行所需的数据与堆栈分开存储。这允许异步执行的顺序代码(例如,在没有显式回调的情况下处理非阻塞I/O),还支持惰性计算无限序列上的算法和其他用途。
协程类图如下:
协程类

2 实例-计算斐波那契序列

2.1 斐波那契序列

斐波那契数列是一位意大利的数学家,他闲着没事去研究兔子繁殖的过程,研究着就发现,可以写成这么一个序列:1,1,2,3,5,8,13,21… 也就是每个数等于它前两个数之和。那么给你第 n 个数,问 F (n) 是多少。
用数学公式表示很简单: f(n) = f(n-1) + f(n-2)
下面的例子使用协程来计算斐波那契序列

2.2 代码

#include <coroutine>
#include <cstdint>
#include <exception>
#include <iostream>template <typename T>
struct Generator
{struct promise_type;using handle_type = std::coroutine_handle<promise_type>;struct promise_type{T value_;std::exception_ptr exception_;Generator get_return_object(){return Generator(handle_type::from_promise(*this));}std::suspend_always initial_suspend() { return {}; }std::suspend_always final_suspend() noexcept { return {}; }void unhandled_exception() { exception_ = std::current_exception(); }template<std::convertible_to<T> From>std::suspend_always yield_value(From&& from)//设置完值后挂起协程{value_ = std::forward<From>(from);return {};}void return_void() {}};handle_type h_;Generator(handle_type h) : h_(h) {}~Generator() { h_.destroy(); }explicit operator bool(){fill();return !h_.done();}T operator()(){fill();full_ = false;return std::move(h_.promise().value_);}
private:bool full_ = false;void fill(){if(!full_){h_();//if(h_.promise().exception_)std::rethrow_exception(h_.promise().exception_);full_ = true;}}
};Generator<std::uint64_t>
fibonacci_sequence(unsigned n)//斐波那契序列
{if(n == 0)co_return;//计算结束 if(n > 94)throw std::runtime_error("太大斐波那契序列,元素将会溢出");co_yield 0;//挂起协程if(n == 1)co_return;//计算结束co_yield 1;if(n == 2)co_return;std::uint64_t a = 0;std::uint64_t b = 1;for(unsigned i = 2; i < n; ++i){std::uint64_t s = a + b;co_yield s;//挂起协程a = b;b = s;}//计算结束
}int main(int argc, char *argv[])
{int n = 10;if(argc > 1)n = std::stoul(argv[1]);try{auto gen = fibonacci_sequence(n);for(int j = 0; gen; ++j)//调用operator bool()判断是gen是否计算结束std::cout << "fib(" << j << ")=" << gen() << std::endl;//调用T operator()()返回计算j对应的斐波那契序列值}catch(const std::exception& e){std::cerr << "异常: " << e.what() << std::endl;}catch(...){std::cerr << "未知异常\n";}return 0;
}

3 运行

$./example2 0
$./example2 0 1
fib(0)=0
$./example2 0 4
fib(0)=0
fib(1)=1
fib(2)=1
fib(3)=2
$./example2 0 10
fib(0)=0
fib(1)=1
fib(2)=1
fib(3)=2
fib(4)=3
fib(5)=5
fib(6)=8
fib(7)=13
fib(8)=21
fib(9)=34
$./example2 95
异常: 太大斐波那契序列,元素将会溢出

这篇关于C++并发之协程实例(二)(计算斐波那契序列)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1081763

相关文章

利用c++判断水仙花数并输出示例代码

《利用c++判断水仙花数并输出示例代码》水仙花数是指一个三位数,其各位数字的立方和恰好等于该数本身,:本文主要介绍利用c++判断水仙花数并输出的相关资料,文中通过代码介绍的非常详细,需要的朋友可以... 以下是使用C++实现的相同逻辑代码:#include <IOStream>#include <vec

基于C++的UDP网络通信系统设计与实现详解

《基于C++的UDP网络通信系统设计与实现详解》在网络编程领域,UDP作为一种无连接的传输层协议,以其高效、低延迟的特性在实时性要求高的应用场景中占据重要地位,下面我们就来看看如何从零开始构建一个完整... 目录前言一、UDP服务器UdpServer.hpp1.1 基本框架设计1.2 初始化函数Init详解

C++ 右值引用(rvalue references)与移动语义(move semantics)深度解析

《C++右值引用(rvaluereferences)与移动语义(movesemantics)深度解析》文章主要介绍了C++右值引用和移动语义的设计动机、基本概念、实现方式以及在实际编程中的应用,... 目录一、右值引用(rvalue references)与移动语义(move semantics)设计动机1

Nginx服务器部署详细代码实例

《Nginx服务器部署详细代码实例》Nginx是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务,:本文主要介绍Nginx服务器部署的相关资料,文中通过代码... 目录Nginx 服务器SSL/TLS 配置动态脚本反向代理总结Nginx 服务器Nginx是一个‌高性

C++ move 的作用详解及陷阱最佳实践

《C++move的作用详解及陷阱最佳实践》文章详细介绍了C++中的`std::move`函数的作用,包括为什么需要它、它的本质、典型使用场景、以及一些常见陷阱和最佳实践,感兴趣的朋友跟随小编一起看... 目录C++ move 的作用详解一、一句话总结二、为什么需要 move?C++98/03 的痛点⚡C++

Go异常处理、泛型和文件操作实例代码

《Go异常处理、泛型和文件操作实例代码》Go语言的异常处理机制与传统的面向对象语言(如Java、C#)所使用的try-catch结构有所不同,它采用了自己独特的设计理念和方法,:本文主要介绍Go异... 目录一:异常处理常见的异常处理向上抛中断程序恢复程序二:泛型泛型函数泛型结构体泛型切片泛型 map三:文

详解C++ 存储二进制数据容器的几种方法

《详解C++存储二进制数据容器的几种方法》本文主要介绍了详解C++存储二进制数据容器,包括std::vector、std::array、std::string、std::bitset和std::ve... 目录1.std::vector<uint8_t>(最常用)特点:适用场景:示例:2.std::arra

C++构造函数中explicit详解

《C++构造函数中explicit详解》explicit关键字用于修饰单参数构造函数或可以看作单参数的构造函数,阻止编译器进行隐式类型转换或拷贝初始化,本文就来介绍explicit的使用,感兴趣的可以... 目录1. 什么是explicit2. 隐式转换的问题3.explicit的使用示例基本用法多参数构造

C++,C#,Rust,Go,Java,Python,JavaScript的性能对比全面讲解

《C++,C#,Rust,Go,Java,Python,JavaScript的性能对比全面讲解》:本文主要介绍C++,C#,Rust,Go,Java,Python,JavaScript性能对比全面... 目录编程语言性能对比、核心优势与最佳使用场景性能对比表格C++C#RustGoJavapythonjav

C++打印 vector的几种方法小结

《C++打印vector的几种方法小结》本文介绍了C++中遍历vector的几种方法,包括使用迭代器、auto关键字、typedef、计数器以及C++11引入的范围基础循环,具有一定的参考价值,感兴... 目录1. 使用迭代器2. 使用 auto (C++11) / typedef / type alias