青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Impossible is nothing  
  愛(ài)過(guò)知情重醉過(guò)知酒濃   花開(kāi)花謝終是空   緣份不停留像春風(fēng)來(lái)又走   女人如花花似夢(mèng)
公告
日歷
<2025年9月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011
統(tǒng)計(jì)
  • 隨筆 - 8
  • 文章 - 91
  • 評(píng)論 - 16
  • 引用 - 0

導(dǎo)航

常用鏈接

留言簿(4)

隨筆分類(4)

隨筆檔案(8)

文章分類(77)

文章檔案(91)

相冊(cè)

搜索

  •  

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

 

首先,C++標(biāo)準(zhǔn)中提到,一個(gè)編譯單元[translation unit]是指一個(gè).cpp文件以及它所include的所有.h文件,.h文件里的代碼將會(huì)被擴(kuò)展到包含它的.cpp文件里,然后編譯器編譯該.cpp文件為一個(gè).obj文件,后者擁有PE[Portable Executable,windows可執(zhí)行文件]文件格式,并且本身包含的就已經(jīng)是二進(jìn)制碼,但是,不一定能夠執(zhí)行,因?yàn)椴⒉槐WC其中一定有main函數(shù)。當(dāng)編譯器將一個(gè)工程里的所有.cpp文件以分離的方式編譯完畢后,再由連接器(linker)進(jìn)行連接成為一個(gè).exe文件。

舉個(gè)例子:

//---------------test.h-------------------//

    void f();//這里聲明一個(gè)函數(shù)f

//---------------test.cpp--------------//

    #include”test.h”

    void f()

    {

      …//do something

    }  //這里實(shí)現(xiàn)出test.h中聲明的f函數(shù)

//---------------main.cpp--------------//

    #include”test.h”

    int main()

    {

       f(); //調(diào)用ff具有外部連接類型

    }

在這個(gè)例子中,test. cppmain.cpp各被編譯成為不同的.obj文件[姑且命名為test.objmain.obj],在main.cpp中,調(diào)用了f函數(shù),然而當(dāng)編譯器編譯main.cpp時(shí),它所僅僅知道的只是main.cpp中所包含的test.h文件中的一個(gè)關(guān)于void f();的聲明,所以,編譯器將這里的f看作外部連接類型,即認(rèn)為它的函數(shù)實(shí)現(xiàn)代碼在另一個(gè).obj文件中,本例也就是test.obj,也就是說(shuō),main.obj中實(shí)際沒(méi)有關(guān)于f函數(shù)的哪怕一行二進(jìn)制代碼,而這些代碼實(shí)際存在于test.cpp所編譯成的test.obj中。在main.obj中對(duì)f的調(diào)用只會(huì)生成一行call指令,像這樣:

     call f [C++中這個(gè)名字當(dāng)然是經(jīng)過(guò)mangling[處理]過(guò)的]

在編譯時(shí),這個(gè)call指令顯然是錯(cuò)誤的,因?yàn)?/SPAN>main.obj中并無(wú)一行f的實(shí)現(xiàn)代碼。那怎么辦呢?這就是連接器的任務(wù),連接器負(fù)責(zé)在其它的.obj[本例為test.obj]尋找f的實(shí)現(xiàn)代碼,找到以后將call f這個(gè)指令的調(diào)用地址換成實(shí)際的f的函數(shù)進(jìn)入點(diǎn)地址。需要注意的是:連接器實(shí)際上將工程里的.obj“連接”成了一個(gè).exe文件,而它最關(guān)鍵的任務(wù)就是上面說(shuō)的,尋找一個(gè)外部連接符號(hào)在另一個(gè).obj中的地址,然后替換原來(lái)的“虛假”地址。

這個(gè)過(guò)程如果說(shuō)的更深入就是:

      call f這行指令其實(shí)并不是這樣的,它實(shí)際上是所謂的stub,也就是一個(gè)

      jmp 0x23423[這個(gè)地址可能是任意的,然而關(guān)鍵是這個(gè)地址上有一行指令來(lái)進(jìn)行真正的call f動(dòng)作。也就是說(shuō),這個(gè).obj文件里面所有對(duì)f的調(diào)用都jmp向同一個(gè)地址,在后者那兒才真正”call”f。這樣做的好處就是連接器修改地址時(shí)只要對(duì)后者的call XXX地址作改動(dòng)就行了。但是,連接器是如何找到f的實(shí)際地址的呢[在本例中這處于test.obj],因?yàn)?/SPAN>.obj.exe的格式都是一樣的,在這樣的文件中有一個(gè)符號(hào)導(dǎo)入表和符號(hào)導(dǎo)出表[import tableexport table]其中將所有符號(hào)和它們的地址關(guān)聯(lián)起來(lái)。這樣連接器只要在test.obj的符號(hào)導(dǎo)出表中尋找符號(hào)f[當(dāng)然C++對(duì)f作了mangling]的地址就行了,然后作一些偏移量處理后[因?yàn)槭菍蓚€(gè).obj文件合并,當(dāng)然地址會(huì)有一定的偏移,這個(gè)連接器清楚]寫(xiě)入main.obj中的符號(hào)導(dǎo)入表中f所占有的那一項(xiàng)。

這就是大概的過(guò)程。其中關(guān)鍵就是:

    編譯main.cpp時(shí),編譯器不知道f的實(shí)現(xiàn),所有當(dāng)碰到對(duì)它的調(diào)用時(shí)只是給出一個(gè)指示,指示連接器應(yīng)該為它尋找f的實(shí)現(xiàn)體。這也就是說(shuō)main.obj中沒(méi)有關(guān)于f的任何一行二進(jìn)制代碼。

    編譯test.cpp時(shí),編譯器找到了f的實(shí)現(xiàn)。于是乎f的實(shí)現(xiàn)[二進(jìn)制代碼]出現(xiàn)在test.obj里。

    連接時(shí),連接器在test.obj中找到f的實(shí)現(xiàn)代碼[二進(jìn)制]的地址[通過(guò)符號(hào)導(dǎo)出表]。然后將main.obj中懸而未決的call XXX地址改成f實(shí)際的地址。

    完成。

 

 

然而,對(duì)于模板,你知道,模板函數(shù)的代碼其實(shí)并不能直接編譯成二進(jìn)制代碼,其中要有一個(gè)“具現(xiàn)化”的過(guò)程。舉個(gè)例子:

//----------main.cpp------//

 template<class T>

 void f(T t)

 {}

 int main()

 {

   …//do something

   f(10); //call f<int> 編譯器在這里決定給f一個(gè)f<int>的具現(xiàn)體

   …//do other thing

  }

也就是說(shuō),如果你在main.cpp文件中沒(méi)有調(diào)用過(guò)ff也就得不到具現(xiàn),從而main.obj中也就沒(méi)有關(guān)于f的任意一行二進(jìn)制代碼??!如果你這樣調(diào)用了:

  f(10); //f<int>得以具現(xiàn)化出來(lái)

f(10.0); //f<double>得以具現(xiàn)化出來(lái)

這樣main.obj中也就有了f<int>,f<double>兩個(gè)函數(shù)的二進(jìn)制代碼段。以此類推。

然而具現(xiàn)化要求編譯器知道模板的定義,不是嗎?

看下面的例子:[將模板和它的實(shí)現(xiàn)分離]

 //-------------test.h----------------//

    template<class T>

    class A

    {

     public:

        void f(); //這里只是個(gè)聲明

     };

//---------------test.cpp-------------//

  #include”test.h”

  template<class T>

  void A<T>::f()  //模板的實(shí)現(xiàn),但注意:不是具現(xiàn)

  {

    …//do something

  }

//---------------main.cpp---------------//

   #include”test.h”

   int main()

   {

      A<int> a;

a.        f(); //編譯器在這里并不知道A<int>::f的定義,因?yàn)樗辉?/SPAN>test.h里面

   //于是編譯器只好寄希望于連接器,希望它能夠在其他.obj里面找到

   //A<int>::f的實(shí)現(xiàn)體,在本例中就是test.obj,然而,后者中真有A<int>::f

   //二進(jìn)制代碼嗎?NO?。?!因?yàn)?/SPAN>C++標(biāo)準(zhǔn)明確表示,當(dāng)一個(gè)模板不被用到的時(shí)

   //侯它就不該被具現(xiàn)出來(lái),test.cpp中用到了A<int>::f了嗎?沒(méi)有!!所以實(shí)

   //際上test.cpp編譯出來(lái)的test.obj文件中關(guān)于A::f的一行二進(jìn)制代碼也沒(méi)有

   //于是連接器就傻眼了,只好給出一個(gè)連接錯(cuò)誤

   //但是,如果在test.cpp中寫(xiě)一個(gè)函數(shù),其中調(diào)用A<int>::f,則編譯器會(huì)將其//具現(xiàn)出來(lái),因?yàn)樵谶@個(gè)點(diǎn)上[test.cpp],編譯器知道模板的定義,所以能//夠具現(xiàn)化,于是,test.obj的符號(hào)導(dǎo)出表中就有了A<int>::f這個(gè)符號(hào)的地

//址,于是連接器就能夠完成任務(wù)。

         }


        
關(guān)鍵是:在分離式編譯的環(huán)境下,編譯器編譯某一個(gè).cpp文件時(shí)并不知道另一個(gè).cpp文件的存在,也不會(huì)去查找[當(dāng)遇到未決符號(hào)時(shí)它會(huì)寄希望于連接器]。這種模式在沒(méi)有模板的情況下運(yùn)行良好,但遇到模板時(shí)就傻眼了,因?yàn)槟0鍍H在需要的時(shí)候才會(huì)具現(xiàn)化出來(lái),所以,當(dāng)編譯器只看到模板的聲明時(shí),它不能具現(xiàn)化該模板,只能創(chuàng)建一個(gè)具有外部連接的符號(hào)并期待連接器能夠?qū)⒎?hào)的地址決議出來(lái)。然而當(dāng)實(shí)現(xiàn)該模板的.cpp文件中沒(méi)有用到模板的具現(xiàn)體時(shí),編譯器懶得去具現(xiàn),所以,整個(gè)工程的.obj中就找不到一行模板具現(xiàn)體的二進(jìn)制代碼,于是連接器也黔驢技窮了。

posted on 2006-02-25 18:31 笑笑生 閱讀(168) 評(píng)論(0)  編輯 收藏 引用 所屬分類: C++語(yǔ)言
 
Copyright © 笑笑生 Powered by: 博客園 模板提供:滬江博客
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美激情综合在线| 欧美成人免费小视频| 国产精品尤物福利片在线观看| 另类春色校园亚洲| 你懂的视频欧美| 欧美大片一区二区| 欧美日韩精品欧美日韩精品 | 欧美激情在线播放| 亚洲国产欧美一区| 欧美成人精品在线观看| 亚洲第一页在线| 亚洲精品1区2区| 99在线视频精品| 亚洲一区二区少妇| 久久久久久久久久久久久女国产乱| 欧美在线亚洲在线| 欧美电影在线观看| 国产精品入口尤物| 激情懂色av一区av二区av| 最新国产成人av网站网址麻豆| 亚洲最新合集| 久久国产精品久久w女人spa| 美女图片一区二区| 一区二区av| 久久综合伊人77777尤物| 欧美日韩中文字幕日韩欧美| 国产综合在线看| 亚洲视频在线观看一区| 久久久久久久97| 91久久精品美女高潮| 小黄鸭视频精品导航| 美乳少妇欧美精品| 国产精品久久精品日日| 91久久久精品| 久久久另类综合| 一区二区三区高清| 亚洲午夜高清视频| 日韩视频免费| 久久久久久久久久码影片| 亚洲丰满少妇videoshd| 欧美在线在线| 国产欧美一区二区三区沐欲| 99视频精品| 欧美激情视频一区二区三区在线播放 | 国产精品久久久久国产a级| 亚洲国产精品成人一区二区| 欧美一区二区日韩一区二区| 亚洲精品亚洲人成人网| 久久男女视频| 国产一区欧美日韩| 亚洲欧美在线看| 亚洲日本va午夜在线电影| 久热re这里精品视频在线6| 国产精品亚洲产品| 亚洲一二三区精品| 亚洲精选一区| 欧美精品一区二区三区很污很色的 | 国产区二精品视| 亚洲午夜久久久久久久久电影院| 亚洲第一毛片| 久久嫩草精品久久久久| 精久久久久久| 久久免费视频在线| 欧美一进一出视频| 国产亚洲欧美日韩美女| 久久成人免费网| 欧美一级电影久久| 国产一区二区0| 久久午夜羞羞影院免费观看| 欧美在线观看视频| 好看的日韩视频| 欧美 日韩 国产在线| 久色成人在线| 亚洲欧洲另类| 亚洲精品黄色| 欧美日韩在线三级| 亚洲欧美日韩一区二区三区在线| 一本大道久久精品懂色aⅴ | 国产精品久久久久久久第一福利| 国产精品99久久久久久久久| 亚洲一区二区三区在线看 | 在线亚洲欧美视频| 中文久久精品| 欧美精品久久久久久久免费观看 | 欧美成人高清视频| 日韩午夜电影av| 亚洲精品日韩综合观看成人91| 欧美日韩精品综合| 欧美一区永久视频免费观看| 欧美一级播放| 99re热精品| 午夜免费日韩视频| 亚洲精品乱码久久久久久蜜桃麻豆 | 亚洲图片激情小说| 亚洲专区国产精品| 亚洲国产成人tv| 一区二区日韩| 在线观看欧美亚洲| 99这里只有久久精品视频| 国产中文一区二区| 亚洲精品一二三| 国产综合色在线视频区| 亚洲肉体裸体xxxx137| 国产精品一区二区三区免费观看| 美腿丝袜亚洲色图| 国产精品久久久久毛片软件 | 日韩亚洲国产欧美| 国产一区三区三区| 亚洲精品欧美日韩专区| 韩国欧美国产1区| aa级大片欧美| 亚洲激情成人在线| 欧美亚洲免费在线| 中文国产成人精品久久一| 久久这里有精品15一区二区三区| 这里只有精品视频在线| 久久久久一区| 亚洲欧美日韩在线观看a三区| 久久久亚洲精品一区二区三区| 亚洲天堂网在线观看| 欧美1区3d| 玖玖玖国产精品| 国产午夜一区二区三区| av不卡在线| 一区二区三区|亚洲午夜| 久久综合九色综合久99| 久久国产精品久久久久久久久久 | 中国日韩欧美久久久久久久久| 久久夜色精品一区| 久久国产精品久久久久久| 国产精品家教| 日韩视频在线观看免费| 亚洲最黄网站| 欧美日韩在线精品| 最新成人在线| aa级大片欧美三级| 午夜视频精品| 欧美亚洲成人网| 中国女人久久久| 一区二区三区在线观看国产| 乱中年女人伦av一区二区| 亚洲一区二区高清视频| 欧美高清免费| 欧美多人爱爱视频网站| 久久成人免费电影| 蜜桃av噜噜一区二区三区| 国产亚洲制服色| 一区二区三区高清在线观看| 久久婷婷一区| 久久久久久高潮国产精品视| 韩日欧美一区二区三区| 久久大香伊蕉在人线观看热2| 久久福利毛片| 国产一区在线播放| 欧美一级在线亚洲天堂| 久久久国产精品一区二区三区| 国产日本欧美在线观看| 久久精品综合网| 欧美激情精品久久久久久黑人| 亚洲国产网站| 欧美日韩另类字幕中文| 亚洲精品偷拍| 亚洲欧美成aⅴ人在线观看| 国产精品青草久久| 久久久久久久综合| 欧美激情在线狂野欧美精品| 亚洲精品一区二区在线观看| 欧美金8天国| 亚洲无线观看| 久久久亚洲成人| 日韩视频三区| 国产日韩精品一区| 久久综合一区二区三区| 亚洲精品日韩在线| 久久激情中文| 亚洲精品美女久久久久| 国产精品久久精品日日| 久久久精品tv| 中国日韩欧美久久久久久久久| 欧美中文字幕视频| 亚洲国产小视频在线观看| 欧美视频一区二| 久久国产夜色精品鲁鲁99| 亚洲国产精品成人综合色在线婷婷| 一区二区三区高清在线观看| 国产视频一区二区在线观看 | 在线视频欧美一区| 久热精品在线视频| 亚洲永久免费观看| 亚洲成色777777女色窝| 欧美午夜一区| 毛片精品免费在线观看| 午夜一级久久| 亚洲精品韩国| 男女精品视频| 欧美在线一二三区| 国产精品你懂得| 亚洲一区欧美激情| 一区在线免费| 欧美日韩一区在线观看视频|