• <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>

            微塵--KeepMoving

            為了忘卻的記憶
            posts - 3, comments - 2, trackbacks - 0, articles - 13
              C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

            2008年3月7日

             轉(zhuǎn)自 chenxixia 的 Blog

            Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=455591



            設(shè)有一個(gè)Win32下的可執(zhí)行文件MyApp.exe,這是一個(gè)Win32應(yīng)用程序,符合標(biāo)準(zhǔn)的PE格式。MyApp.exe的主要執(zhí)行代碼都集中在其源文件MyApp.cpp中,該文件第一個(gè)被執(zhí)行的函數(shù)是WinMain。初學(xué)者會(huì)認(rèn)為程序就是首先從這個(gè)WinMain函數(shù)開(kāi)始執(zhí)行,其實(shí)不然。

                在WinMain函數(shù)被執(zhí)行之前,有一系列復(fù)雜的加載動(dòng)作,還要執(zhí)行一大段啟動(dòng)代碼。運(yùn)行程序MyApp.exe時(shí),操作系統(tǒng)的加載程序首先為進(jìn)程分配一個(gè)4GB的虛擬地址空間,然后把程序MyApp.exe所占用的磁盤空間作為虛擬內(nèi)存映射到這個(gè)4GB的虛擬地址空間中。一般情況下,會(huì)映射到虛擬地址空間中0X00400000的位置。加載一個(gè)應(yīng)用程序的時(shí)間比一般人所設(shè)想的要少,因?yàn)榧虞d一個(gè)PE文件并不是把這個(gè)文件整個(gè)一次性的從磁盤讀到內(nèi)存中,而是簡(jiǎn)單的做一個(gè)內(nèi)存映射,映射一個(gè)大文件和映射一個(gè)小文件所花費(fèi)的時(shí)間相差無(wú)幾。當(dāng)然,真正執(zhí)行文件中的代碼時(shí),操作系統(tǒng)還是要把存在于磁盤上的虛擬內(nèi)存中的代碼交換到物理內(nèi)存(RAM)中。但是,這種交換也不是把整個(gè)文件所占用的虛擬地址空間一次性的全部從磁盤交換到物理內(nèi)存中,操作系統(tǒng)會(huì)根據(jù)需要和內(nèi)存占用情況交換一頁(yè)或多頁(yè)。當(dāng)然,這種交換是雙向的,即存在于物理內(nèi)存中的一部分當(dāng)前沒(méi)有被使用的頁(yè)也可能被交換到磁盤中。

                接著,系統(tǒng)在內(nèi)核中創(chuàng)建進(jìn)程對(duì)象和主線程對(duì)象以及其它內(nèi)容。

                然后操作系統(tǒng)的加載程序搜索PE文件中的引入表,加載所有應(yīng)用程序所使用的動(dòng)態(tài)鏈接庫(kù)。對(duì)動(dòng)態(tài)鏈接庫(kù)的加載與對(duì)應(yīng)用程序的加載完全類似。

                再接著,操作系統(tǒng)執(zhí)行PE文件首部所指定地址處的代碼,開(kāi)始應(yīng)用程序主線程的執(zhí)行。首先被執(zhí)行的代碼并不是MyApp中的WinMain函數(shù),而是被稱為C Runtime startup code的WinMainCRTStartup函數(shù),該函數(shù)是連接時(shí)由連接程序附加到文件MyApp.exe中的。該函數(shù)得到新進(jìn)程的全部命令行指針和環(huán)境變量的指針,完成一些C運(yùn)行時(shí)全局變量以及C運(yùn)行時(shí)內(nèi)存分配函數(shù)的初始化工作。如果使用C++編程,還要執(zhí)行全局類對(duì)象的構(gòu)造函數(shù)。最后,WinMainCRTStartup函數(shù)調(diào)用WinMain函數(shù)。

               WinMainCRTStartup函數(shù)傳給WinMain函數(shù)的4個(gè)參數(shù)分別為:hInstance、hPrevInstance、lpCmdline、nCmdShow。

                hInstance:該進(jìn)程所對(duì)應(yīng)的應(yīng)用程序當(dāng)前實(shí)例的句柄。WinMainCRTStartup函數(shù)通過(guò)調(diào)用GetStartupInfo函數(shù)獲得該參數(shù)的值。該參數(shù)實(shí)際上是應(yīng)用程序被加載到進(jìn)程虛擬地址空間的地址,通常情況下,對(duì)于大多數(shù)進(jìn)程,該參數(shù)總是0X00400000。

                hPrevInstance:應(yīng)用程序前一實(shí)例的句柄。由于Win32應(yīng)用程序的每一個(gè)實(shí)例總是運(yùn)行在自己的獨(dú)立的進(jìn)程地址空間中,因此,對(duì)于Win32應(yīng)用程序,WinMainCRTStartup函數(shù)傳給該參數(shù)的值總是NULL。如果應(yīng)用程序希望知道是否有另一個(gè)實(shí)例在運(yùn)行,可以通過(guò)線程同步技術(shù),創(chuàng)建一個(gè)具有唯一名稱的互斥量,通過(guò)檢測(cè)這個(gè)互斥量是否存在可以知道是否有另一個(gè)實(shí)例在運(yùn)行。

                lpCmdline:命令行參數(shù)的指針。該指針指向一個(gè)以0結(jié)尾的字符串,該字符串不包括應(yīng)用程序名。

                nCmdShow:指定如何顯示應(yīng)用程序窗口。如果該程序通過(guò)在資源管理器中雙擊圖標(biāo)運(yùn)行,WinMainCRTStartup函數(shù)傳給該參數(shù)的值為SW_SHOWNORMAL。如果通過(guò)在另一個(gè)應(yīng)用程序中調(diào)用CreatProcess函數(shù)運(yùn)行,該參數(shù)由CreatProcess函數(shù)的參數(shù)lpStartupInfo(STARTUPINFO.wShowWindow)指定。



             

            posted @ 2008-03-07 16:38 微塵 閱讀(664) | 評(píng)論 (0)編輯 收藏

            2008年2月29日

             

             

            本文檔深入分析了std::deque,并提供了一個(gè)指導(dǎo)思想:當(dāng)考慮到內(nèi)存分配和執(zhí)行性能的時(shí)候,使用std::deque要比std::vector好。

              介紹

              本文深入地研究了std::deque 容器。本文將討論在一些情況下使用deque> 比vector更好。讀完這篇文章后讀者應(yīng)該能夠理解在容量增長(zhǎng)的過(guò)程中deque 與vector在內(nèi)存分配和性能的不同表現(xiàn)。由于deque> 和vector的用法很相似,讀者可以參考vector 文檔中介紹如何使用STL容器。

              Deque總覽

              deque和vector一樣都是標(biāo)準(zhǔn)模板庫(kù)中的內(nèi)容,deque是雙端隊(duì)列,在接口上和vector非常相似,在許多操作的地方可以直接替換。假如讀者已經(jīng)能夠有效地使用vector容器,下面提供deque的成員函數(shù)和操作,進(jìn)行對(duì)比參考。

              Deque成員函數(shù)

            函數(shù)
            描述
            c.assign(beg,end)
            c.assign(n,elem)
            將[beg; end)區(qū)間中的數(shù)據(jù)賦值給c。
            將n個(gè)elem的拷貝賦值給c。
            c.at(idx)
            傳回索引idx所指的數(shù)據(jù),如果idx越界,拋出out_of_range。
            c.back()
            傳回最后一個(gè)數(shù)據(jù),不檢查這個(gè)數(shù)據(jù)是否存在。
            c.begin()
            傳回迭代器重的可一個(gè)數(shù)據(jù)。
            c.clear()
            移除容器中所有數(shù)據(jù)。
            deque<Elem> c
            deque<Elem> c1(c2)
            Deque<Elem> c(n)
            Deque<Elem> c(n, elem)
            Deque<Elem> c(beg,end)
            c.~deque<Elem>()
            創(chuàng)建一個(gè)空的deque。
            復(fù)制一個(gè)deque。
            創(chuàng)建一個(gè)deque,含有n個(gè)數(shù)據(jù),數(shù)據(jù)均已缺省構(gòu)造產(chǎn)生。
            創(chuàng)建一個(gè)含有n個(gè)elem拷貝的deque。
            創(chuàng)建一個(gè)以[beg;end)區(qū)間的deque。
            銷毀所有數(shù)據(jù),釋放內(nèi)存。
            c.empty()
            判斷容器是否為空。
            c.end()
            指向迭代器中的最后一個(gè)數(shù)據(jù)地址。
            c.erase(pos)
            c.erase(beg,end)
            刪除pos位置的數(shù)據(jù),傳回下一個(gè)數(shù)據(jù)的位置。
            刪除[beg,end)區(qū)間的數(shù)據(jù),傳回下一個(gè)數(shù)據(jù)的位置。
            c.front()
            傳回地一個(gè)數(shù)據(jù)。
            get_allocator
            使用構(gòu)造函數(shù)返回一個(gè)拷貝。
            c.insert(pos,elem)
            c.insert(pos,n,elem)
            c.insert(pos,beg,end)
            在pos位置插入一個(gè)elem拷貝,傳回新數(shù)據(jù)位置。
            在pos位置插入>n個(gè)elem數(shù)據(jù)。無(wú)返回值。
            在pos位置插入在[beg,end)區(qū)間的數(shù)據(jù)。無(wú)返回值。
            c.max_size()
            返回容器中最大數(shù)據(jù)的數(shù)量。
            c.pop_back()
            刪除最后一個(gè)數(shù)據(jù)。
            c.pop_front()
            刪除頭部數(shù)據(jù)。
            c.push_back(elem)
            在尾部加入一個(gè)數(shù)據(jù)。
            c.push_front(elem)
            在頭部插入一個(gè)數(shù)據(jù)。
            c.rbegin()
            傳回一個(gè)逆向隊(duì)列的第一個(gè)數(shù)據(jù)。
            c.rend()
            傳回一個(gè)逆向隊(duì)列的最后一個(gè)數(shù)據(jù)的下一個(gè)位置。
            c.resize(num)
            重新指定隊(duì)列的長(zhǎng)度。
            c.size()
            返回容器中實(shí)際數(shù)據(jù)的個(gè)數(shù)。
            C1.swap(c2)
            Swap(c1,c2)
            將c1和c2元素互換。
            同上操作。

              Deque操作

            函數(shù)
            描述
            operator[]
            返回容器中指定位置的一個(gè)引用。

              上面這些特征和vector明顯相似,所以我們會(huì)提出下面的疑問(wèn)。

              問(wèn)題:如果deque和vector可以提供相同功能的時(shí)候,我們使用哪一個(gè)更好呢?

              回答:如果你要問(wèn)的話,就使用vector吧。

              或者你給個(gè)解釋?

              非常高興你這樣問(wèn),的確,這并不是無(wú)中生有的,事實(shí)上,在C++標(biāo)準(zhǔn)里解釋了這個(gè)問(wèn)題,下面有一個(gè)片斷:

              vector在默認(rèn)情況下是典型的使用序列的方法,對(duì)于deque,當(dāng)使用插入刪除操作的時(shí)候是一個(gè)更好的選擇。

              有趣的是,本文就是要非常徹底地理解這句話。

              什么是新的?

              細(xì)讀上面兩張表格,你會(huì)發(fā)現(xiàn)和vector比較這里增加了兩個(gè)函數(shù)。

              1、c.push_front(elem) —— 在頭部插入一個(gè)數(shù)據(jù)。

              2、c.pop_front() —— 刪除頭部數(shù)據(jù)。

              調(diào)用方法和c.push_back(elem)和c.pop_back()相同,這些將來(lái)會(huì)告訴我們對(duì)于deque> 會(huì)非常有用,deque可以在前后加入數(shù)據(jù)。>

              缺少了什么?

              同時(shí)你也會(huì)發(fā)現(xiàn)相對(duì)于vector> 缺少了兩個(gè)函數(shù),你將了解到deque> 不需要它們。

              1、capacity()—— 返回vector當(dāng)前的容量。

              2、reserve() —— 給指定大小的vector> 分配空間。

              這里是我們真正研究的開(kāi)始,這里說(shuō)明deque> 和vector它們?cè)诠芾韮?nèi)部存儲(chǔ)的時(shí)候是完全不同的。deque是大塊大塊地分配內(nèi)存,每次插入固定數(shù)量的數(shù)據(jù)。vector是就近分配內(nèi)存(這可能不是一個(gè)壞的事情)。但我們應(yīng)該關(guān)注是,vector每次增加的內(nèi)存足夠大的時(shí)候,在當(dāng)前的內(nèi)存不夠的情況。下面的實(shí)驗(yàn)來(lái)驗(yàn)證deque不需要capacity()和reserve()> 是非常有道理的。

              實(shí)驗(yàn)一 —— 增長(zhǎng)的容器

              目的

              目的是通過(guò)實(shí)驗(yàn)來(lái)觀察deque和vector在容量增長(zhǎng)的時(shí)候有什么不同。用圖形來(lái)說(shuō)明它們?cè)诜峙鋬?nèi)存和執(zhí)行效率上的不同。

              描述

              這個(gè)實(shí)驗(yàn)的測(cè)試程序是從一個(gè)文件中讀取文本內(nèi)容,每行作為一個(gè)數(shù)據(jù)使用push_back插入到deque> 和vector中,通過(guò)多次讀取文件來(lái)實(shí)現(xiàn)插入大量的數(shù)據(jù),下面這個(gè)類就是為了測(cè)試這個(gè)內(nèi)容:

            #include <deque>
            #include <fstream>
            #include <string>
            #include <vector>

            static enum modes
            {
             FM_INVALID = 0,
             FM_VECTOR,
             FM_DEQUE
            };

            class CVectorDequeTest
            {
             public:
              CVectorDequeTest();
              void ReadTestFile(const char* szFile, int iMode)
              {
               char buff[0xFFFF] = {0};
               std::ifstream inFile;
               inFile.open(szFile);
               while(!inFile.eof())
               {
                inFile.getline(buff, sizeof(buff));
                if(iMode == FM_VECTOR)
                 m_vData.push_back(buff);
                else if(iMode == FM_DEQUE)
                 m_dData.push_back(buff);
               }
               inFile.close();
              }
              virtual ~CVectorDequeTest();
             protected:
              std::vector<std::string> m_vData;
              std::deque<std::string> m_dData;
            };


              結(jié)果

              測(cè)試程序運(yùn)行的平臺(tái)和一些條件:

            CPU 1.8 GHz Pentium 4
            內(nèi)存 1.50 GB
            操作系統(tǒng) W2K-SP4
            文件中的行數(shù) 9874
            平均每行字母?jìng)€(gè)數(shù)
            1755.85
            讀文件的次數(shù)
            45
            總共插入的數(shù)據(jù)個(gè)數(shù) 444330


              使用Windows任務(wù)管理器來(lái)記錄執(zhí)行效率,本程序中使用了Laurent Guinnard 的CDuration類。消耗系統(tǒng)資源如下圖:


              注意在vector分配內(nèi)存的最高峰,vector在分配內(nèi)存的時(shí)候是怎樣達(dá)到最高值,deque就是這樣的,它在插入數(shù)據(jù)的同時(shí),內(nèi)存直線增長(zhǎng),首先deque的這種內(nèi)存分配單元進(jìn)行回收的話,存在意想不到的后果,我們希望它的分配內(nèi)存看上去和vector一樣,通過(guò)上面的測(cè)試我們需要進(jìn)一步的測(cè)試,現(xiàn)提出一個(gè)假設(shè):假設(shè)deque分配的內(nèi)存不是連續(xù)的,一定需要釋放和收回內(nèi)存,我們將這些假設(shè)加入后面的測(cè)試中,但是首先讓我們從執(zhí)行的性能外表分析一下這個(gè)實(shí)驗(yàn)。

              究竟分配內(nèi)存需要消耗多久?

              注意看下面這張圖片,vector在不插入數(shù)據(jù)的時(shí)候在進(jìn)行尋求分配更多內(nèi)存。


              同時(shí)我們也注意到使用push_back插入一組數(shù)據(jù)消耗的時(shí)間,注意,在這里每插入一組數(shù)據(jù)代表著9874個(gè)串,平均每個(gè)串的長(zhǎng)度是1755.85。

             

            實(shí)驗(yàn)二—— vector::reserve()的資源

              目的

              這個(gè)實(shí)驗(yàn)的目的是vector在加入大量數(shù)據(jù)之前調(diào)用reserve(),和deque進(jìn)行比較,看它們的內(nèi)存分配和執(zhí)行效率怎么樣?

              描述

              本實(shí)驗(yàn)中的測(cè)試基本上和實(shí)驗(yàn)一相同,除了在測(cè)試類的構(gòu)造函數(shù)中加入下面這行代碼:

            m_vData.reserve(1000000);

              結(jié)果

              測(cè)試程序運(yùn)行的平臺(tái)和一些條件:

            CPU
            1.8 GHz Pentium 4
            內(nèi)存
            1.50 GB
            操作系統(tǒng)
            W2K-SP4
            文件中的行數(shù)
            9874
            平均每行字母?jìng)€(gè)數(shù)
            1755.85
            讀文件的次數(shù)
            70
            總共插入的數(shù)據(jù)個(gè)數(shù)
            691180

              使用Windows任務(wù)管理器來(lái)記錄執(zhí)行效率,本程序中使用了>Laurent Guinnard 的CDuration類。消耗系統(tǒng)資源如下圖:


              我們注意到vector不在需要分配花費(fèi)多余的時(shí)間分配內(nèi)存了,這是由于我們使用了reserve()對(duì)于所測(cè)試的>691180個(gè)數(shù)據(jù)為我們每一次插入大量數(shù)據(jù)的時(shí)候保留了足夠的內(nèi)存空間,對(duì)于deque存儲(chǔ)分配的假設(shè),觀察這個(gè)測(cè)試中的內(nèi)存分配圖形和上一個(gè)圖形,我們需要進(jìn)一步量化這個(gè)測(cè)試。

              怎樣改良內(nèi)存分配的性能呢?

              下面這個(gè)圖例說(shuō)明隨著數(shù)據(jù)的增加,容量在增加:


              當(dāng)增加數(shù)據(jù)的時(shí)候?qū)θ萘康脑黾釉趘ector和deque執(zhí)行效率基本一樣,然而,vector在插入數(shù)據(jù)的時(shí)候有一些零星的時(shí)間消耗,看下面的圖例:


              通過(guò)統(tǒng)計(jì)分析vector和deque在插入平均為>1755.85長(zhǎng)度的>9874個(gè)數(shù)據(jù)所花費(fèi)的時(shí)間,下面是總結(jié)的表格:


            Vector

            Deque

            Mean

            0.603724814 sec

            Maximum

            0.738313000 sec

            Minimum

            0.559959000 sec


            Std. Dev

            0.037795736 sec

            6-Sigma

            0.226774416 sec

            Mean

            0.588021114 sec

            Maximum

            0.615617000 sec

            Minimum

            0.567503000 sec

            Std. Dev

            0.009907800 sec

            6-Sigma

            0.059446800 sec


              實(shí)驗(yàn)三——內(nèi)存回收

              目的

              本實(shí)驗(yàn)是對(duì)假設(shè)deque分配的內(nèi)存不是臨近的,而且很難回收進(jìn)行量化測(cè)試分析。

              描述

              在本實(shí)驗(yàn)中再次用到了實(shí)驗(yàn)一中的代碼,在調(diào)用函數(shù)中加入記錄增加數(shù)據(jù)執(zhí)行的效率具體入下面操作:

            for(xRun=0; xRun<NUMBER_OF_XRUNS; xRun++)
            {
             df = new CVectorDequeTest;
             elapsed_time = 0;

             for(i=0; i<NUMBER_OF_RUNS*xRun; i++)
             {
              cout << "Deque - Run " << i << " of " <<
              NUMBER_OF_RUNS*xRun << "... ";
              df->ReadTestFile("F:\\huge.csv",DF_DEQUE);
              deque_data.push_back(datapoint());
              deque_data.back().time_to_read = df->GetProcessTime();
              elapsed_time += deque_data.back().time_to_read;
              deque_data.back().elapsed_time = elapsed_time;
              cout << deque_data.back().time_to_read << " seconds\n";
             }
             vnElements.push_back(df->GetDequeSize());
             cout << "\n\nDeleting... ";
             del_deque.Start();
             delete df;
             del_deque.Stop();
             cout << del_deque.GetDuration()/1000000.0 << " seconds.\n\n";
             vTimeToDelete.push_back(del_deque.GetDuration()/1000000.0);
            }

              結(jié)果

              本測(cè)試和上面兩個(gè)實(shí)驗(yàn)在相同的平臺(tái)上運(yùn)行,除了插入的數(shù)據(jù)由>9874到>691180,需要插入>70次,下面圖例顯示了>deque在插入數(shù)據(jù)的時(shí)候分配內(nèi)存的情況,在deque里插入了平均每個(gè)長(zhǎng)度為>1755.85的字符串。>


              盡管從幾個(gè)曲線圖中看到的實(shí)際消耗時(shí)間不同,但些曲線圖都精確到了>R2=95.15%。所給的數(shù)據(jù)點(diǎn)都實(shí)際背離了下表中統(tǒng)計(jì)的曲線圖數(shù)據(jù):

            deque Results

            Mean

            0.007089269 sec

            Maximum

            11.02838496 sec

            Minimum

            -15.25901667 sec

            Std. Dev

            3.3803636 sec

            6-Sigma

            20.2821816 sec

              在相同的情況下比較vector的結(jié)果是非常有意義的。下面圖就是將vector和deque在相同的情況下分配內(nèi)存消耗的時(shí)間比較圖:


              這些數(shù)據(jù)在這個(gè)測(cè)試中是>R2=82.12%。這或許可以經(jīng)過(guò)每個(gè)點(diǎn)反復(fù)運(yùn)行得到更加優(yōu)化,在這個(gè)問(wèn)題中這些數(shù)據(jù)適當(dāng)?shù)貥?biāo)注了這些點(diǎn),所給的數(shù)據(jù)點(diǎn)都實(shí)際背離了下表中統(tǒng)計(jì)的曲線圖數(shù)據(jù):


            vector Results

            Mean

            -0.007122715sec

            Maximum

            0.283452127 sec

            Minimum

            -0.26724459sec

            Std. Dev

            0.144572356sec

            6-Sigma

            0.867434136sec


            實(shí)驗(yàn)四—— vector::insert() 和 deque::insert() 執(zhí)行特點(diǎn)比較

              目的

              deque主張使用參數(shù)為常量的insert()。但怎么樣能和vector::insert()比較一下呢?本實(shí)驗(yàn)的目的就是比較一下vector::insert()> 和 deque::insert()的工作特點(diǎn)。

              描述

              在容器的容器多次插入數(shù)據(jù),在這里可能不符合你的需求,既然這樣你可以使用insert(),試驗(yàn)代碼也和實(shí)驗(yàn)一基本一樣,使用insert()代替push_back(),使用insert(>)來(lái)測(cè)試。

              結(jié)果

              當(dāng)插入常量給deque的時(shí)候,從下圖可以看出和vector的對(duì)比來(lái)。


              注意兩張圖片中時(shí)間軸的不同,這是將>61810個(gè)數(shù)據(jù)插入到容器中。


              實(shí)驗(yàn)五——讀取容器的性能

              目的

              這個(gè)實(shí)驗(yàn)將測(cè)試vector::at(),vector::operator[],deque::at()和deque::operator[]的性能。首先應(yīng)該是operator[]比at()效率要高,因?yàn)樗贿M(jìn)行邊界檢查,同時(shí)也比較vector和deque。

              描述

              這個(gè)實(shí)驗(yàn)將測(cè)試中的容器有1000000個(gè)類型為std::string,每個(gè)字符串長(zhǎng)度為1024的數(shù)據(jù),分別使用at()和operator[]這兩個(gè)操作來(lái)訪問(wèn)容器容器的數(shù)據(jù),測(cè)試它們運(yùn)行的時(shí)間,這個(gè)測(cè)試執(zhí)行50次,統(tǒng)計(jì)每次執(zhí)行的結(jié)果。

              結(jié)果

              我們看到使用vector和deque訪問(wèn)容器中的數(shù)據(jù),他們執(zhí)行的性能差別很小,使用operator[]和at()訪問(wèn)數(shù)據(jù)的性能差別幾乎可以忽略不計(jì),下面是統(tǒng)計(jì)的結(jié)果:


            vector::at()

            Mean

            1.177088125sec

            Maximum

            1.189580000sec

            Minimum

            1.168340000sec

            Std. Dev

            0.006495193sec

            6-Sigma

            0.038971158sec

            deque::at()

            Mean

            1.182364375sec

            Maximum

            1.226860000sec

            Minimum

            1.161270000sec

            Std. Dev

            0.016362148sec

            6-Sigma

            0.098172888sec

            vector::operator[]

            Mean

            1.164221042sec

            Maximum

            1.192550000sec

            Minimum

            1.155690000sec

            Std. Dev

            0.007698520sec

            6-Sigma

            0.046191120sec

            deque::operator[]

            Mean

            1.181507292sec

            Maximum

            1.218540000 sec

            Minimum

            1.162710000sec

            Std. Dev

            0.010275712sec

            6-Sigma

            0.061654272sec

              結(jié)論

              在這篇文章中我們覆蓋了多種不同的情況來(lái)選擇我們到底是該使用vector還是deque。讓我們總結(jié)一下測(cè)試的結(jié)果看下面幾個(gè)結(jié)論。

              當(dāng)執(zhí)行大數(shù)據(jù)量的調(diào)用push_back()的時(shí)候,記住要調(diào)用vector::reserve()。

              在實(shí)驗(yàn)一中我們研究了vector和deque在插入數(shù)據(jù)的情況。通過(guò)這些假設(shè),我們可以看出deque分配的空間是預(yù)先分配好的,deque維持一個(gè)固定增長(zhǎng)率,在vector實(shí)驗(yàn)中我們考慮到應(yīng)該調(diào)用vecor::reserve()>.然后在下面這個(gè)例子驗(yàn)證了我們的假設(shè),在使用vector的時(shí)候調(diào)用reserve()能夠膀子我們預(yù)先分配空間,這將是vector一個(gè)默認(rèn)選擇的操作。

              當(dāng)你分配很多內(nèi)存單元的時(shí)候,記住使用deque回收內(nèi)存要比vector消耗時(shí)間多。

              在實(shí)驗(yàn)三中我們探討了vector和deque在回收非鄰接內(nèi)存塊上的不同,分別證明了vector在分配內(nèi)存的時(shí)候是線性增長(zhǎng),而deque是指數(shù)增長(zhǎng),同樣,vector要回收的內(nèi)存比deque多的多,如果你循環(huán)調(diào)用了push_back(),那么deque將獲取大量的內(nèi)存,而且是臨近的。我們通過(guò)測(cè)試發(fā)現(xiàn)在分配內(nèi)存單元消耗的時(shí)間和vector的時(shí)間接近。

              如果你計(jì)劃使用insert(),或者需要pop_front(),那就使用deque。

              由于vector沒(méi)有提供pop_front()函數(shù),但在實(shí)驗(yàn)四的結(jié)果中可以看出沒(méi)有insert()是非常好的,同時(shí)也告訴我們?yōu)槭裁磀eque在STL類中要作為單獨(dú)的一個(gè)類劃分出來(lái)。

              對(duì)于訪問(wèn)數(shù)據(jù),vector::at()效率最高。

              在實(shí)驗(yàn)五中統(tǒng)計(jì)的數(shù)據(jù)表示,所有訪問(wèn)數(shù)據(jù)方法的效率是非常接近的,但是vector::at()效率最高。這是因?yàn)樽顑?yōu)的平衡圖訪問(wèn)時(shí)間為最低的六個(gè)西格瑪值。

              最后

              我希望本文能夠帶你認(rèn)識(shí)deque,而且對(duì)它感興趣或者一個(gè)啟發(fā),歡迎繼續(xù)討論關(guān)于vector和deque任何問(wèn)題和內(nèi)容。

            posted @ 2008-02-29 22:04 微塵 閱讀(675) | 評(píng)論 (0)編輯 收藏

            2008年2月25日

             
                   相信大家在編碼中,有時(shí)會(huì)見(jiàn)到某某函數(shù)前面加了 extern "C" 的關(guān)鍵字修飾,尤其在模塊(Dll)提供的頭文件中。但是否很清楚的了解它的作用, 我當(dāng)時(shí)第一次碰到時(shí),其實(shí)是懂非懂的^_^。查了些資料,才明白其用法,詳細(xì)如下。

                  1. 首先說(shuō)下編譯器編譯函數(shù)時(shí),對(duì)函數(shù)名的處理。
                     在C語(yǔ)言中,對(duì)函數(shù)如: IRoleView* RoleViewCreate(int nType); 編譯后生成的函數(shù)名是RoleViewCreate
                     但是在C++中,由于存在函數(shù)重載的特性,所以編譯時(shí)C++編譯器會(huì)根據(jù)參數(shù)、返回值等信息對(duì)函數(shù)名改編,如上面函數(shù)在C++編譯器中生成的函數(shù)名是 ?RoleViewCreate@@YAPAVIRoleView@@H@z
                  
                 2. extern "C"的含義。
                     extern "C" 有兩重含義:
                    其一,被修飾的變量或函數(shù)是extern的存儲(chǔ)類型,它告訴編譯器,其聲明的變量或函數(shù)可以被本模塊和外部某塊使用。
                    其二,被其修飾的函數(shù)或變量是按照C語(yǔ)言的方式來(lái)編譯和鏈接的。
                    注意,extern "C"寫(xiě)法 只在C++中被支持,C語(yǔ)言不支持該寫(xiě)法。
               
                3. extern "C"的兩種慣用用法:
                    a) 在C++中使用C語(yǔ)言的函數(shù)或變量,在包含C語(yǔ)言提供的頭文件是,需要用 extern "C" { } 來(lái)包含頭文件。如下:
                       extern "C"
                      {
                           #include "lua.h"    //lua.h是C編寫(xiě),并提供的頭文件
                      }
                    這里引用下第1點(diǎn)的函數(shù)來(lái)說(shuō)明上述寫(xiě)法的用途:假設(shè)lua.h中包含函數(shù) IRoleView* RoleViewCreate(int nType), 那么C語(yǔ)言的編譯時(shí)生成的函數(shù)名是RoleViewCreate,而當(dāng)C++客戶程序去使用它時(shí),默認(rèn)是按C++的鏈接方式(即不加以上的 extern "C"時(shí)),所以C++客戶程序會(huì)去外部模塊中查找函數(shù)名為
            ?RoleViewCreate@@YAPAVIRoleView@@H@z的函數(shù),這樣C++編譯器會(huì)找不到該函數(shù),報(bào)出"無(wú)法解析的外部標(biāo)識(shí)符"的錯(cuò)誤; 而當(dāng)加上
            extern "C" { } 時(shí),它就告訴編譯器頭文件中包含的函數(shù)或變量要按照C語(yǔ)言的編譯鏈接方式進(jìn)行,所以C++編譯器會(huì)去外部模塊查找函數(shù)名為
            RoleViewCreate的函數(shù),從而得到正確結(jié)果。

                  b) 在C中調(diào)用一個(gè)C++語(yǔ)言中的函數(shù)或變量時(shí),C++的頭文件需要添加 extern "C",這是為了讓編譯器對(duì)函數(shù)或變量按C語(yǔ)言的方式進(jìn)行編譯,已供C語(yǔ)言調(diào)用; 但在C語(yǔ)言中,不能直接包含聲明了extern "C"的頭文件,而應(yīng)該在C文件中把在C++頭文件中定義的函數(shù),聲明為 extern類型,因?yàn)樵贑語(yǔ)言中,并不支持extern "C"的寫(xiě)法;

            參考資料:《C++中extern "C" 含義深層探索》作者:宋寶華
                                《C++ Primer》
                    

            posted @ 2008-02-25 20:46 微塵 閱讀(551) | 評(píng)論 (0)編輯 收藏

            久久婷婷人人澡人人| 青青草国产精品久久久久| 久久WWW免费人成—看片| 久久久久亚洲精品无码网址 | 亚洲乱码日产精品a级毛片久久 | 国产亚州精品女人久久久久久 | 久久亚洲精品中文字幕| 久久香蕉一级毛片| 中文成人久久久久影院免费观看| 18岁日韩内射颜射午夜久久成人| 国产午夜精品久久久久免费视| 久久成人精品| 69国产成人综合久久精品| 久久人人超碰精品CAOPOREN| 日韩精品久久久肉伦网站| 久久伊人色| 久久99国产亚洲高清观看首页| 一级女性全黄久久生活片免费 | 国产精品久久久天天影视香蕉 | 97久久精品人人做人人爽| 亚洲精品蜜桃久久久久久| 久久这里只有精品视频99| 国产国产成人精品久久| 久久综合偷偷噜噜噜色| 99久久免费国产精品| 国产∨亚洲V天堂无码久久久| 尹人香蕉久久99天天拍| 日韩欧美亚洲综合久久影院Ds| 51久久夜色精品国产| 国产韩国精品一区二区三区久久| 久久人人爽人人爽人人AV东京热| 亚洲国产成人久久一区久久| 久久九九免费高清视频| 国产精品一区二区久久精品无码 | 久久精品中文騷妇女内射| 精品熟女少妇AV免费久久| 香蕉久久夜色精品国产2020| 亚洲精品成人久久久| 久久亚洲精品国产亚洲老地址| 欧洲国产伦久久久久久久| 伊人久久精品影院|