实现序号生成器
函数(Function)
#include <cassert> int id_generator(int& base, int step) { int result = *base; *base += step; return result; } int main(int argc, char *argv[]) { int odd_base = 1; int even_base = 0; assert(id_generator(odd_base, 2) == 1); assert(id_generator(odd_base, 2) == 3); assert(id_generator(odd_base, 2) == 5); assert(id_generator(even_base, 2) == 0); assert(id_generator(even_base, 2) == 2); assert(id_generator(even_base, 2) == 4); return 0; }
- 编译
g++ -g add.cpp -o add
闭包(Closure)
#include <cassert> int main(int argc, char *argv[]) { int base = 1; auto id_generator_odd = [=]() mutable { int result = base; base += 2; return result; }; base = 0; auto id_generator_even = [=]() mutable { int result = base; base += 2; return result; }; assert(id_generator_odd() == 1); assert(id_generator_odd() == 3); assert(id_generator_odd() == 5); assert(id_generator_even() == 0); assert(id_generator_even() == 2); assert(id_generator_even() == 4); assert(base == 0); return 0; }
- 编译
g++ -g closure.cpp -o closure -std=c++0x
协程(Coroutine)
#include <boost/bind.hpp> #include <boost/coroutine/all.hpp> typedef boost::coroutines::coroutine< int(void) > IDGenerator; void idGenerator(IDGenerator::caller_type& ca, int base, int step) { do{ ca(base); base += step; }while(true); } int main(int argc, char *argv[]) { IDGenerator id_generator_odd(boost::bind(idGenerator, _1, 1, 2)); IDGenerator id_generator_even(boost::bind(idGenerator, _1, 0, 2)); assert(id_generator_odd.get() == 1); assert(id_generator_odd().get() == 3); assert(id_generator_odd().get() == 5); assert(id_generator_even.get() == 0); assert(id_generator_even().get() == 2); assert(id_generator_even().get() == 4); return 0; }
- 编译
g++ -g coroutine.cpp -lboost_context -o coroutine -std=c++0x
特性比较
函数(Function)
- 无状态
- 需要独立定义执行体
- 调用过程中从头到尾执行体内所有代码
- 在输入相同的情况下,能够保证输出也相同
- 没有副作用,多线程安全
- 要借助外部变量保存状态
- 调用比较麻烦,需要传入保存状态的参数
闭包(Closure)
- 有状态,内部直接保存
- 直接内联定义执行体
- 调用过程中从头到尾执行体内所有代码
- 输入相同的情况下,输出可能不同
- 有副作用,非多线程安全
- 定义时可以多种方式安全地引用外部变量
- 调用简单,不需要传入保存状态的参数
协程(Coroutine)
- 有状态,内部直接保存
- 需要独立定义执行体
- 调用过程中直接从上次的运行状态继续运行
- 输入相同的情况下,输出可能不同
- 严禁多线程访问
- 调用简单,不需要传入保存状态的参数