• <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++博客 首頁 新隨筆 聯系 聚合 管理
              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;
            }
            };
            // 經驗: 保存lambda表達式的變量被銷毀后,該表達式對應的閉包會銷毀。應該保證閉包在lambda表達式變量的生命周期之內執行,否則程序執行結果不可預知!
            // 1.理解lambda首先要理解函數對象,和閉包
            // 2.理解必包的基礎上,理解lambda如何實現閉包
            // 3.理解閉包以后,需要分析設置不同的capture的情況下分別是如何實現閉包
            //   1)閉包意味著一個函數地址 + 一組封裝好的參數。
            //   2)閉包可以被拷貝,但是每個閉包中的參數可以是不一樣的
            // 4.理解函數對象和lambda的關系: lambda可以理解成函數,但是當lambda賦值給一個函數對象的時候,編譯器應該是把lambda構造成了一個閉包的function
            //   1)根據匯編碼分析,lambda對象類似于函數指針(但是類型系統和函數指針是完全不同的概念,可以用decltype(lambda)來鑒定),本質和函數對象是不一樣的。
            //   2)定義一個lambda表達式相當于定義一個函數(觀察會變碼,lambda表達式是沒有構造和析構的)
            //   3)把函數指針賦值給一個std::function,和吧lambda賦值給一個std::function的效果是完全不一樣的。一個這是指針賦值操作,另一個則是完整的閉包。
            //   4)經過代碼實際測試,lambda是鑒于函數指針和函數對象之間的一個玩意,它也是一個特殊的類型,這個具體只能看C++標準文檔了。
            //   5)boost asio異步接口中的functor可能是利用了meta編程技巧,或者他本身每一次發起異步操作都會形成一個獨立的閉包,解決了函數對象和socket對象生命周期綁定的關系
            //      應為如果是functor實現,宿主對象析構,一定會造成作為成員變量的functor銷毀,同時引起lambda閉包混亂(不僅閉包參數亂掉,閉包函數本身也呈現混亂)。
            //      由此分析,閉包中的任何一行代碼都必須在閉包本身的聲明周期內執行。似乎可以理解成,lambda閉包是把lambda函數本身也當作一個特殊的參數來完成閉包封裝的。
            //      通過會變碼觀察,在使用不同的lambda變量調用lambda表達式的時候,會在ecx寄存器壓入不同的值,然后會讀取一塊關聯的內存。
            //   6)vc2015下的lambda永遠都是4字節,這應該是編譯器實現細節了,按說應該是隨著閉包內容的大小變化而變化。我猜測,這四個字節應該指向一個塊內存,里邊的數據是用來還原“lambda”函數執行棧的閉包
            // 5.通俗的理解上述分析: lambda對象(變量)是一塊內存,內存里邊是lambda表達式本身的副本。當執行lambda表達式對象的時候,實際是執行對象對應的內存中的代碼,如果對象被析構了,對應的代碼也就是未知代碼。
            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)();  // 調用后整個閉包混亂
            }
            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; 編譯錯誤,應為編譯器會把每一個lambda表達式當作一個獨立的類型,這是lambda不同于函數指針的地方,函數指針是根據參數來決定類型的
            decltype(lambda) lambda_copy = lambda;
            *pFunc = lambda2;
            }
            func();
            (*pFunc)();
            }
            posted on 2017-03-22 22:41 Enic 閱讀(1854) 評論(0)  編輯 收藏 引用 所屬分類: C/C++技巧
            久久久久成人精品无码中文字幕| 国产精品久久久久久久久鸭 | 色播久久人人爽人人爽人人片AV| 99久久香蕉国产线看观香| 久久丫精品国产亚洲av不卡| 久久综合久久综合久久| 亚洲伊人久久成综合人影院 | 欧美日韩精品久久久免费观看| 天堂久久天堂AV色综合| 久久亚洲av无码精品浪潮| 久久久一本精品99久久精品88| 久久青青草原精品国产软件| 99国产欧美精品久久久蜜芽| 亚洲美日韩Av中文字幕无码久久久妻妇 | 精品久久久无码中文字幕天天| 777午夜精品久久av蜜臀| 99久久国产亚洲高清观看2024 | 一本一本久久a久久精品综合麻豆| 国产精品视频久久| 久久亚洲精精品中文字幕| 久久精品视频一| 99久久亚洲综合精品成人| 69SEX久久精品国产麻豆| 亚洲va国产va天堂va久久| 久久综合久久美利坚合众国| 久久综合成人网| 久久精品国产亚洲一区二区三区 | 久久国产精品二国产精品| 国产精品无码久久四虎| 91久久福利国产成人精品| 久久91亚洲人成电影网站| 丁香五月网久久综合| 欧美牲交A欧牲交aⅴ久久 | 国内精品久久久久国产盗摄| 91性高湖久久久久| 久久嫩草影院免费看夜色| 无码国内精品久久人妻麻豆按摩| 久久久精品视频免费观看| 久久综合九色欧美综合狠狠| 亚洲日韩欧美一区久久久久我| 久久婷婷是五月综合色狠狠|