在.net 4.0中增加一个延迟加载类Lazy<T>,它的作用是实现按需延迟加载,也许很多人用过。一个典型的应用场景是这样的:当初始化某个对象时,该对象引用了一个大对象,需要创建,这个对象的创建时需要较长的时间,同时也需要在托管堆上分配较多的空间,这样可能会在初始化时变得很慢,尤其是UI应用时,会导致用户体验很差。其实狠多时候并不需要马上就获取大数据,只是在需要时获取,这种场景就很适合延迟加载了。先看看c#中Lazy<T>如何使用的吧:

class LargeObject
{
public int InitializedBy { get { return initBy; } } int initBy = ;
public LargeObject(int initializedBy)
{
initBy = initializedBy;
Console.WriteLine("LargeObject was created on thread id {0}.", initBy);
} public long[] Data = new long[];
}
class TestLazy
{
Lazy<LargeObject> lazyLargeObject = null; public TestLazy()
{
//创建一个延迟加载对象
lazyLargeObject = new Lazy<LargeObject>(InitLargeObject);
} public void ReallyLoad()
{
//此时真正加载
lazyLargeObject.Value;
Console.WriteLine("lazy load big object"); //do something
}
} void Test()
{
TestLazy t = new TestLazy();
t.ReallyLoad(); //这时,真正延迟加载时才会打印"lazy load big object"
}

  

  c++中目前还没有类似的Lazy<T>延迟加载类,其实延迟加载类内部用到了lamda表达式,将函数封装到lamda表达式中去,而不是马上求值,而是在需要的时候再调用lamda表达式去求值。c++11 中有lamda表达式和function,正好做这个事情,看看c++11如何实现类似c#的Lazy<T>延迟加载类吧。

#include <boost/optional.hpp>
template<typename T>
struct Lazy
{
Lazy(){} template <typename Func, typename... Args>
Lazy(Func& f, Args && ... args)
{
m_func = [&f, &args...]{return f(args...); };
} T& Value()
{
if (!m_value.is_initialized())
{
m_value = m_func();
} return *m_value;
} bool IsValueCreated() const
{
return m_value.is_initialized();
} private:
std::function<T()> m_func;
boost::optional<T> m_value;
}; template<class Func, typename... Args>
Lazy<typename std::result_of<Func(Args...)>::type>
lazy(Func && fun, Args && ... args)
{
return Lazy<typename std::result_of<Func(Args...)>::type>(std::forward<Func>(fun), std::forward<Args>(args)...);
}

再看看测试代码:

struct BigObject
{
BigObject()
{
cout << "lazy load big object" << endl;
}
}; struct MyStruct
{
MyStruct()
{
m_obj = lazy([]{return std::make_shared<BigObject>(); });
} void Load()
{
m_obj.Value();
} Lazy< std::shared_ptr<BigObject>> m_obj;
}; int Foo(int x)
{
return x * ;
} void TestLazy()
{
//带参数的普通函数
int y = ;
auto lazyer1 = lazy(Foo, y);
cout << lazyer1.Value() << endl; //不带参数的lamda
Lazy<int> lazyer2 = lazy([]{return ; });
cout << lazyer2.Value() << endl; //带参数的fucntion
std::function < int(int) > f = [](int x){return x + ; };
auto lazyer3 = lazy(f, );
cout << lazyer3.Value() << endl; //延迟加载大对象
MyStruct t;
t.Load();
}

输出结果:


lazy laod big object

  这个Lazy<T>类可以接收lamda表达式和function,实现按需延迟加载。和c#的Lazy<T>用法类似。不过还没c#中Laze<T>那么强大,没有增加线程策略在里面,目前还不想做得更复杂,简单够用就行。

c++11 boost技术交流群:296561497,欢迎大家来交流技术。

(原创)一个和c#中Lazy<T>类似的c++ Lazy<T>类的实现的更多相关文章

  1. 一个java源文件中为什么只能有一个public类。

    我们都遇到过一个源文件中有多个java类,但当第一个类使用public修饰时,如果下面还有类使用public修饰,会报错.也就是是说一个java源文件最多只能有一个public类. 当有一个publi ...

  2. 22.编写一个类A,该类创建的对象可以调用方法showA输出小写的英文字母表。然后再编写一个A类的子类B,子类B创建的对象不仅可以调用方法showA输出小写的英文字母表,而且可以调用子类新增的方法showB输出大写的英文字母表。最后编写主类C,在主类的main方法 中测试类A与类B。

    22.编写一个类A,该类创建的对象可以调用方法showA输出小写的英文字母表.然后再编写一个A类的子类B,子类B创建的对象不仅可以调用方法showA输出小写的英文字母表,而且可以调用子类新增的方法sh ...

  3. 1.一个.java源文件中是否可以包括多个类?2...

    1.一个“.java”源文件中是否可以包括多个类(不是内部类)?有什么限制? 答:可以有多个类,但只能有一个public类,并且public的类名必须与文件名相一致. 2.java有没有goto? 答 ...

  4. 第7章 一个java源文件中只能有一个public类

    一个Java源文件中最多只能有一个public类, 1)当有一个public类时,源文件名必须与之一致,否则无法编译, 2)如果源文件中没有一个public类,则文件名与类中没有一致性要求. 至于ma ...

  5. 一个".java"源文件中是否可以包括多个类

    可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致. 现在我们编个测试文件来测试一番(一个程序员要具有用于探索的精神   -.-     手动滑稽) 1.编写一个 a ...

  6. 为什么一个java源文件中只能有一个public类

    问题:一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制? 答案:可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致.一个文件 ...

  7. 浅谈为什么一个java源文件中只能有一个public类?

    声明,本篇文章为转载 转载 http://blog.csdn.net/bareheadzzq/article/details/6562211 最近在一个java文件中实现了几个类,其中一个声明为pub ...

  8. [PY3]——找出一个序列中出现次数最多的元素/collections.Counter 类的用法

    问题 怎样找出一个序列中出现次数最多的元素呢? 解决方案 collections.Counter 类就是专门为这类问题而设计的, 它甚至有一个有用的 most_common() 方法直接给了你答案 c ...

  9. 一个.java源文件中可以有多个类吗?(内部类除外)有什么条件?

    一个.java源文件中可以有多个类吗?(内部类除外)有什么条件?带着这个疑惑,动手建几个测试类, 揭开心中的疑惑.以下是解开疑惑过程: package test;/** * 一个.java源文件中可以 ...

  10. Java.基础 -------- 一个Java源文件中可以有很多类,但只能有一个类是public的

    一个Java源文件中可以有很多类,但只能有一个类是public的        Java程序是从一个public类main函数开始执行的,只能有一个public是为了给类装载器提供方便,一个publi ...

随机推荐

  1. DirectX中文手册

    目  录 第一章 DirectX基础(初级篇) 第一节  什么是DirectX 一.什么是DirectX ? 二.DirectX的组成部分 三.关于DirectDraw 四.为什么要使用DirectD ...

  2. win32下编译glog

    既然编译第三方库了,google提供的VSproject是老版本的,构建不好升级.所以还是用cmake是王道. 采用out of source 编译,  以下是编译脚本bat: mkdir build ...

  3. 远程阿里云window服务器报错身份验证错误

    整理文章,很久之前遇到的一个问题,一直呆在草稿箱,特发布出来,帮助可能遇到该问题的人 mstsc连接时报错如下 解决方法: 修改本地安全组策略[安全组  gpedit.msc]

  4. 使用perf + FlameGraph生成进程火焰图

    FlameGraph代码:https://github.com/cobblau/FlameGraph 使用方法 1,perf record --call-graph dwarf -p 12345 2, ...

  5. 转载:Kafka 之 中级 原作者:悟性

    Kafka 之 中级 悟性 发表于 3年前 阅读 21353 摘要: Kafka配置介绍,原理介绍及生产者,消费者Java基本使用方法. 1.    配置 Ø  Broker主要配置 参数 默认值 说 ...

  6. HDU 4324 Triangle LOVE (拓扑排序)

    Triangle LOVE Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tot ...

  7. uploadify.js参数说明(转)

    一.属性 属性名称 默认值 说明 auto true 设置为true当选择文件后就直接上传了,为false需要点击上传按钮才上传 . buttonClass ” 按钮样式 buttonCursor ‘ ...

  8. 强制IE浏览器或WebBrowser控件

    注册表: 32 bit: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BRO ...

  9. PowerDesigner之PDM(物理概念模型)各种属性建立如PK,AK等

    一.PDM概述 PDM(物理数据模型),通俗地理解,就是在PowerDesigner中以图形化的方式展示和设计数据库. PDM中涉及到的基本概念包括: 表: 列: 视图: 主键: 候选键: 外键: 存 ...

  10. cmake3.8X64编译opencv3.2出现opencv_ffmpeg、opencv_ffmpeg_64、ippicv_windows_20151201.zip无法下载问题解决方案

    cmake版本:cmake3.8.0 开发环境:Visual Studio 2017 x64 解决方法:1.在opencv安装目录下sources\3rdparty\ffmpeg\ffmpeg.cma ...