• <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>
            C++分析研究  
            C++
            日歷
            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567
            統計
            • 隨筆 - 92
            • 文章 - 4
            • 評論 - 4
            • 引用 - 0

            導航

            常用鏈接

            留言簿

            隨筆檔案

            文章檔案

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

             
              我們曾經在討論C++的時候,經常會問到:“虛函數能被聲明為內聯嗎?”現在,我們幾乎聽不到這個問題了。現在聽到的是:“你不應該使print成為內聯的。聲明一個虛函數為內聯是錯誤的!”

              這種說法的兩個主要的原因是(1)虛函數是在運行期決議而內聯是一個編譯期動作,所以,我們將虛函數聲明為內聯并得不到什么效果;(2)聲明一個虛函數為內聯導致了函數的多分拷貝,而且我們為一個不應該在任何時候內聯的函數白白花費了存儲空間。這樣做很沒腦子。 www.601456.com

              不過,事實并不是這樣。我們先來看看第一個:許多情況下,虛擬函數都被靜態地決議了——比如在派生類虛擬函數中調用基類的虛擬函數的時候。為什么這樣做呢?封裝。一個比較明顯的例子就是派生類析構函數調用鏈。所有的虛析構函數,除了最初觸發這個析構鏈的虛析構函數,都被靜態的決議了。如果不將基類的虛析構函數內聯,我們無法從中獲利[a]。這和不內聯一個虛擬析構函數有什么不同嗎?如果繼承體系層次比較深并且有許多這樣的類的實例要被銷毀的話,答案是肯定的。

              再來看另外一個不用析構函數的例子,想象一下設計一個圖書館類。我們將MaterialLocation作為抽象類LibraryMaterial的一個成員。將它的print成員函數聲明為一個純虛函數,并且提供函數定義:它輸出MaterialLocation。

              class LibraryMaterial {

              private:

              MaterialLocation _loc; // shared data

              // ...

              public:

              // declares pure virtual function

              inline virtual void print( ostream& = cout ) = 0;

              };

              // we actually want to encapsulate the handling of the

              // location of the material within a base class

              // LibraryMaterial print() method - we just don’t want it

              // invoked through the virtual interface. That is, it is

              // only to be invoked within a derived class print() method

              inline void

              LibraryMaterial::

              print( ostream &os ) { os <<_loc; }

              接著,我們引入一個Book類,它的print函數輸出Title, Author等等。在這之前,它調用基類的print函數(LibraryMaterial::print())來顯示書本位置(MaterialLocation)。如下:

              inline void

              Book:: www.liuhebao.com

              print( ostream &os )

              {

              // ok, this is resolved statically,

              // and therefore is inline expanded ...

              LibraryMaterial::print();

              os <<"title:" <<_title

              << "author" <<_author < www.szfuao.com

              AudioBook類,派生于Book類,并加入附加信息,比如旁述,音頻格式等等。這些東西都用它的print函數輸出。再這之前,我們需要調用Book::print()來顯示前面的信息。

              inline void

              AudioBook::

              print( ostream &os )

              {

              // ok, this is resolved statically,

              // and therefore is inline expanded ...

              Book::print(); www.yzjxsp.com

              os <<"narrator:" <<_narrator <

              }

              這和虛析構函數調用鏈的例子一樣,都只是最初調用的虛函數沒有被靜態決議,其它的都被原地展開。This unnamed hierarchical design pattern is significantly less effective if we never declare a virtual function to be inline.

              那么對于第二個原因中代碼膨脹的問題呢?我們來分析一下,如果我們寫下:

              LibraryMaterial *p =

              new AudioBook( "Mason &Dixon",

              "Thomas Pynchon", "Johnny Depp" );

              // ...

              p->print();

              這個print實例是內聯的嗎?不,當然不是。這樣不得不通過虛擬機制在運行期決議。這讓print實例放棄了對它的內聯聲明了嗎?也不是。這個調用轉換為下面的形式(偽代碼):

              // Pseudo C++Code www.yzsws.com

              // Possible transformation of p->print()

              ( *p->_vptr[ 2 ] )( p );

              where 2 represents the location of print within the associated virtual function table.因為調用print是通過函數指針_vptr[2]進行的,所以,編譯器不能靜態的決定這個調用地址,并且,這個函數也不能內聯。

              當然,虛函數print的內聯實體(definition)也必須在某個地方表現出來。 即是說,至少有一個函數實體是在virtual table調用的地址原地展開的。編譯器是如何決定在何時展開這個函數實體呢?其中一個編譯(implementaion)策略是當virtual table生成的同時,生成這個函數實體。這就是說對于每一個派生類的virtual table都會生成一個函數實體。

              在一個可應用的類[b]中有多少vitrual table會被生成呢?呵呵,這是一個好問題。C++標準中對虛函數行為進行了規定,但是沒有對函數實現進行規定。由于virtual table沒有在C++標準中進行規定,很明顯,究竟這個virtual table怎樣生成,和究竟要生成多少個vitrual table也沒有規定。多少個?當然,我們只要一個。Stroustrup的cfront編譯器,很巧妙的處理了這些情況.( Stan and Andy Koenig described the algorithm in the March 1990 C++ Report article, "Optimizing Virtual Tables in C++ Release 2.0.")

              Moreover, the C++ Standard now requires that inline functions behave as though only one definition for an inline function exists in the program even though the function may be defined in different files。新的規則要求編譯器只展開一個內聯虛函數。如果一點被廣泛采用的話,虛函數的內聯導致的代碼膨脹問題就會消失。 www.yzyedu.com

              [譯注:C++ Standard: 9.3.8, Member function of local class shall be defined inline in their class defination, if they are defined at all]

              ============================

              譯注:

              [a]函數調用開銷,調用基類虛函數的時候至少要經過兩次間接過程(S. B.Lippman: 《Inside the C++ Object Model》)

              [b]一個產品類(?)

              總結:

              就是虛函數inline在調用鏈等地方很有用~

              即使沒有加入inline聲明,作為一個好編譯器,都會優化(虛析構函數)

              在很長的函數調用鏈中,最好將鏈中基類的函數inline,這樣節約開銷

              至于在什么地方inline,由編譯器決定,因為C++標準沒有規定

              新C++標準(可能沒有通過)中,規定了,inline化只對產品類有效,且只動作一次

              保證代碼不過度膨脹

              inline動作是在產品類實例化同時,和vtable生成一起
            posted on 2011-02-20 23:41 HAOSOLA 閱讀(186) 評論(0)  編輯 收藏 引用
             
            Copyright © HAOSOLA Powered by: 博客園 模板提供:滬江博客
            PK10開獎 PK10開獎
            国产欧美久久一区二区| 久久久精品人妻无码专区不卡| 精品久久久久成人码免费动漫| 久久久久av无码免费网| 日本久久久久亚洲中字幕| 久久综合亚洲鲁鲁五月天| 久久综合狠狠综合久久综合88| 久久99久久99小草精品免视看| 国产午夜精品久久久久九九| 麻豆av久久av盛宴av| 久久成人国产精品| 久久五月精品中文字幕| 久久精品国产精品国产精品污| 91精品国产高清久久久久久国产嫩草| 亚洲日韩欧美一区久久久久我| 亚洲AV无码久久| 久久精品国产精品亚洲| 麻豆一区二区99久久久久| 久久国产成人午夜aⅴ影院| 无码超乳爆乳中文字幕久久 | 久久国产福利免费| 久久人人爽人人爽人人AV| 人妻无码精品久久亚瑟影视| 久久99精品国产麻豆宅宅| 久久久久亚洲AV无码网站| 久久妇女高潮几次MBA| 国产精品成人久久久久久久| 久久久久se色偷偷亚洲精品av| 国产2021久久精品| 久久久久四虎国产精品| 精品久久久久久中文字幕人妻最新 | 亚洲AV无码1区2区久久| 久久国产成人午夜AV影院| 91精品国产91久久久久久| 国产精品久久久久国产A级| 久久99精品久久只有精品 | 久久丝袜精品中文字幕| 一级做a爱片久久毛片| 色综合久久精品中文字幕首页| 日日躁夜夜躁狠狠久久AV| 久久亚洲精品人成综合网|