• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Error

            C++博客 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
              217 Posts :: 61 Stories :: 32 Comments :: 0 Trackbacks
            // lambda_test.cpp : Defines the entry point for the console application.
            //
            #include "stdafx.h"
            #include <iostream>
            #include <functional>
            // 利用rtii觀察堆棧生命周期
            class StackLifeTimeWatching
            {
            public:
            StackLifeTimeWatching()
            {
            std::cout << __FUNCTION__ << std::endl;
            }
            ~StackLifeTimeWatching()
            {
            std::cout << __FUNCTION__ << std::endl;
            }
            };
            // 經(jīng)驗(yàn): 保存lambda表達(dá)式的變量被銷毀后,該表達(dá)式對(duì)應(yīng)的閉包會(huì)銷毀。應(yīng)該保證閉包在lambda表達(dá)式變量的生命周期之內(nèi)執(zhí)行,否則程序執(zhí)行結(jié)果不可預(yù)知!
            // 1.理解lambda首先要理解函數(shù)對(duì)象,和閉包
            // 2.理解必包的基礎(chǔ)上,理解lambda如何實(shí)現(xiàn)閉包
            // 3.理解閉包以后,需要分析設(shè)置不同的capture的情況下分別是如何實(shí)現(xiàn)閉包
            //   1)閉包意味著一個(gè)函數(shù)地址 + 一組封裝好的參數(shù)。
            //   2)閉包可以被拷貝,但是每個(gè)閉包中的參數(shù)可以是不一樣的
            // 4.理解函數(shù)對(duì)象和lambda的關(guān)系: lambda可以理解成函數(shù),但是當(dāng)lambda賦值給一個(gè)函數(shù)對(duì)象的時(shí)候,編譯器應(yīng)該是把lambda構(gòu)造成了一個(gè)閉包的function
            //   1)根據(jù)匯編碼分析,lambda對(duì)象類似于函數(shù)指針(但是類型系統(tǒng)和函數(shù)指針是完全不同的概念,可以用decltype(lambda)來(lái)鑒定),本質(zhì)和函數(shù)對(duì)象是不一樣的。
            //   2)定義一個(gè)lambda表達(dá)式相當(dāng)于定義一個(gè)函數(shù)(觀察會(huì)變碼,lambda表達(dá)式是沒(méi)有構(gòu)造和析構(gòu)的)
            //   3)把函數(shù)指針賦值給一個(gè)std::function,和吧lambda賦值給一個(gè)std::function的效果是完全不一樣的。一個(gè)這是指針賦值操作,另一個(gè)則是完整的閉包。
            //   4)經(jīng)過(guò)代碼實(shí)際測(cè)試,lambda是鑒于函數(shù)指針和函數(shù)對(duì)象之間的一個(gè)玩意,它也是一個(gè)特殊的類型,這個(gè)具體只能看C++標(biāo)準(zhǔn)文檔了。
            //   5)boost asio異步接口中的functor可能是利用了meta編程技巧,或者他本身每一次發(fā)起異步操作都會(huì)形成一個(gè)獨(dú)立的閉包,解決了函數(shù)對(duì)象和socket對(duì)象生命周期綁定的關(guān)系
            //      應(yīng)為如果是functor實(shí)現(xiàn),宿主對(duì)象析構(gòu),一定會(huì)造成作為成員變量的functor銷毀,同時(shí)引起lambda閉包混亂(不僅閉包參數(shù)亂掉,閉包函數(shù)本身也呈現(xiàn)混亂)。
            //      由此分析,閉包中的任何一行代碼都必須在閉包本身的聲明周期內(nèi)執(zhí)行。似乎可以理解成,lambda閉包是把lambda函數(shù)本身也當(dāng)作一個(gè)特殊的參數(shù)來(lái)完成閉包封裝的。
            //      通過(guò)會(huì)變碼觀察,在使用不同的lambda變量調(diào)用lambda表達(dá)式的時(shí)候,會(huì)在ecx寄存器壓入不同的值,然后會(huì)讀取一塊關(guān)聯(lián)的內(nèi)存。
            //   6)vc2015下的lambda永遠(yuǎn)都是4字節(jié),這應(yīng)該是編譯器實(shí)現(xiàn)細(xì)節(jié)了,按說(shuō)應(yīng)該是隨著閉包內(nèi)容的大小變化而變化。我猜測(cè),這四個(gè)字節(jié)應(yīng)該指向一個(gè)塊內(nèi)存,里邊的數(shù)據(jù)是用來(lái)還原“lambda”函數(shù)執(zhí)行棧的閉包
            // 5.通俗的理解上述分析: lambda對(duì)象(變量)是一塊內(nèi)存,內(nèi)存里邊是lambda表達(dá)式本身的副本。當(dāng)執(zhí)行l(wèi)ambda表達(dá)式對(duì)象的時(shí)候,實(shí)際是執(zhí)行對(duì)象對(duì)應(yīng)的內(nèi)存中的代碼,如果對(duì)象被析構(gòu)了,對(duì)應(yīng)的代碼也就是未知代碼。
            void Test1();
            void Test2();
            int main()
            {
            Test2();
                return 0;
            }
            void Test2()
            {
            int n = 0;
            auto lambda = [&]()->void
            {
            StackLifeTimeWatching stackWatching;
            n = 1;
            int j = 0;
            int j1 = 0;
            int j2 = 0;
            int j3 = 0;
            int j4 = 0;
            int j5 = 0;
            };
            decltype(&lambda) pLambda0 = &lambda;
            decltype(&lambda) pLambda = NULL;
            int nSize = sizeof(lambda);
            {
            decltype(lambda) lambda_copy = lambda;
            lambda_copy();
            }
            (*pLambda0)();  // 正常掉用
            (*pLambda)();  // 調(diào)用后整個(gè)閉包混亂
            }
            void Test1()
            {
            StackLifeTimeWatching p();
            int n = 0;
            std::function<void()> func;
            std::function<void()>* pFunc = new std::function<void()>;
            {
            //std::function<void()> func = [&]()->void
            //{
            // StackLifeTimeWatching stackWatching;
            // n = 1;
            //};
            //func();
            auto lambda = [&]()->void
            {
            StackLifeTimeWatching stackWatching;
            n = 1;
            };
            lambda();
            func = lambda;
            auto lambda2 = [&]()->void
            {
            delete pFunc;
            pFunc = NULL;
            StackLifeTimeWatching stackWatching;
            n = 1;
            };
            //decltype(lambda) lambda_copy = lambda2; 編譯錯(cuò)誤,應(yīng)為編譯器會(huì)把每一個(gè)lambda表達(dá)式當(dāng)作一個(gè)獨(dú)立的類型,這是lambda不同于函數(shù)指針的地方,函數(shù)指針是根據(jù)參數(shù)來(lái)決定類型的
            decltype(lambda) lambda_copy = lambda;
            *pFunc = lambda2;
            }
            func();
            (*pFunc)();
            }
            posted on 2017-03-22 22:41 Enic 閱讀(1848) 評(píng)論(0)  編輯 收藏 引用 所屬分類: C/C++技巧
            亚洲精品无码久久久久AV麻豆| 久久综合久久综合久久| 久久久黄色大片| 一本一本久久aa综合精品| 国产精品久久久久…| 久久精品国产精品亚洲艾草网美妙| 久久久WWW成人免费精品| 99精品久久精品一区二区| 91麻精品国产91久久久久| 久久强奷乱码老熟女网站| 久久99免费视频| 久久久久亚洲AV无码专区首JN | 久久香蕉国产线看观看99| 精品人妻伦一二三区久久| 欧美一区二区三区久久综合| 国内精品久久久久久久coent| 久久久久人妻一区精品色| 久久人人爽人人精品视频| 日本精品久久久中文字幕| av色综合久久天堂av色综合在| 大蕉久久伊人中文字幕| 国产精品久久精品| 久久精品欧美日韩精品| 无码精品久久久天天影视| 亚洲精品乱码久久久久久蜜桃 | 7777精品伊人久久久大香线蕉| 青青青伊人色综合久久| 精品无码久久久久久尤物| 久久亚洲AV无码精品色午夜| 91超碰碰碰碰久久久久久综合| 99国产欧美精品久久久蜜芽| 亚洲中文字幕久久精品无码APP| 色狠狠久久综合网| 亚洲AV伊人久久青青草原| 久久这里有精品视频| 久久人人爽人人爽人人片AV麻豆| A级毛片无码久久精品免费| 国产精品无码久久四虎| 久久久久香蕉视频| 亚洲精品无码久久毛片| 国产精品成人久久久|