• (原创)一个和c#中Lazy<T>类似的c++ Lazy<T>类的实现


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

    class LargeObject
    {
        public int InitializedBy { get { return initBy; } }
    
        int initBy = 0;
        public LargeObject(int initializedBy)
        {
            initBy = initializedBy;
            Console.WriteLine("LargeObject was created on thread id {0}.", initBy);
        }
    
        public long[] Data = new long[100000000];
    }
    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 * 2;
    }
    
    void TestLazy()
    {
        //带参数的普通函数
        int y = 4;
        auto lazyer1 = lazy(Foo, y);
        cout << lazyer1.Value() << endl;
    
        //不带参数的lamda
        Lazy<int> lazyer2 = lazy([]{return 12; });
        cout << lazyer2.Value() << endl;
    
        //带参数的fucntion
        std::function < int(int) > f = [](int x){return x + 3; };
        auto lazyer3 = lazy(f, 3);
        cout << lazyer3.Value() << endl;
    
        //延迟加载大对象
        MyStruct t;
        t.Load();
    }

    输出结果:

    8
    12
    6
    lazy laod big object

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


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

  • 相关阅读:
    【TensorFlow篇】--Tensorflow框架可视化之Tensorboard
    UTF-8与UTF-8(BOM)区别
    JSP response.setCharacterEncoding与response.setContentType的区别
    Tomcat启动报错org.apache.catalina.core.StandardContext listenerStart
    JS 变量作用域
    JS 函数
    JS中typeof的用法
    JS Map与Set
    JS 选择结构语句与循环结构语句
    JS 对象
  • 原文地址:https://www.cnblogs.com/qicosmos/p/3388704.html
Copyright © 2020-2023  润新知