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

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>
            日韩一级精品视频在线观看| 国产精品久久久一区二区| 久久久蜜桃精品| 欧美色网在线| 亚洲福利专区| 亚洲欧美日韩人成在线播放| 欧美黑人在线播放| 午夜一区在线| 国产精品久久久久天堂| 久久久久久久久综合| 欧美77777| 欧美一区二区啪啪| 国产精品入口麻豆原神| 99国产精品久久久久久久成人热| 亚洲人成久久| 麻豆精品在线播放| 亚洲欧美国产精品专区久久| 欧美视频导航| 久久精品视频一| 性视频1819p久久| 亚洲国产一二三| 久久午夜激情| 久久久久看片| 亚洲一区二区三区国产| 亚洲三级视频| 国产一区二区三区日韩欧美| 久久国产精品亚洲77777| 免费在线一区二区| 亚洲美女诱惑| 日韩手机在线导航| 欧美性事在线| 亚洲一区二区影院| 亚洲一区二区三区乱码aⅴ| 国产精品高清网站| 欧美一区二区啪啪| 欧美一区二区三区在线播放| 一区二区三区黄色| 亚洲一二区在线| 国产欧美日韩精品一区| 久久久久久久999| 欧美日韩中文在线观看| 欧美激情 亚洲a∨综合| 国产婷婷精品| 美女精品视频一区| 欧美成年视频| 亚洲一区二区三区视频| 老司机免费视频一区二区三区| 亚洲人体1000| 亚洲午夜精品一区二区| 亚洲美女中文字幕| 美女在线一区二区| 亚洲桃花岛网站| 亚洲欧美激情一区| 亚洲综合色自拍一区| 欧美激情中文字幕在线| 亚洲欧美一区二区三区极速播放 | 久久久午夜精品| 久久久一本精品99久久精品66| 欧美一区二区在线看| 国产精品二区三区四区| 亚洲无限av看| 午夜日韩福利| 国产网站欧美日韩免费精品在线观看| 亚洲在线1234| 久久精品日韩欧美| 一区二区在线看| 一区二区三区 在线观看视| 好吊妞**欧美| 亚洲一区免费视频| 欧美中文在线免费| 妖精视频成人观看www| 一本色道久久综合亚洲精品按摩| 99国产精品久久久久久久| 欧美日韩免费区域视频在线观看| 亚洲欧洲av一区二区三区久久| 欧美色欧美亚洲高清在线视频| 在线视频你懂得一区| 亚洲国产你懂的| 欧美成人一区二区| 一本一道久久综合狠狠老精东影业 | 羞羞视频在线观看欧美| 久久精品成人| 亚洲日本一区二区三区| 欧美一区二区高清在线观看| 久久综合福利| 99视频精品| 国产一区二区无遮挡| 久久综合给合| 99一区二区| 在线综合亚洲| 国产亚洲福利| 女女同性精品视频| 中文在线资源观看视频网站免费不卡| 亚洲欧美激情视频| 亚洲黄色大片| 国产精品免费在线| 麻豆精品视频在线观看| 亚洲视频图片小说| 欧美成人激情在线| 亚洲一区尤物| 亚洲国产精品999| 国产精品久久久久aaaa九色| 久久久水蜜桃| 亚洲影视综合| 亚洲欧洲在线一区| 亚洲精品日韩激情在线电影| 国产免费观看久久| 欧美一区深夜视频| 亚洲黑丝一区二区| 一区二区欧美国产| 狠狠v欧美v日韩v亚洲ⅴ| 欧美少妇一区| 欧美国产视频在线| 亚洲乱码日产精品bd| 正在播放欧美视频| 亚洲第一福利在线观看| 欧美一区二区在线视频| 99视频在线精品国自产拍免费观看 | 韩国欧美一区| 国产精品夜色7777狼人| 欧美日韩国产黄| 亚洲视频一起| 亚洲美女性视频| 亚洲福利久久| 亚洲一区日本| 中文在线一区| 99视频精品全部免费在线| 亚洲成人自拍视频| 国产一区欧美| 噜噜爱69成人精品| 欧美综合二区| 日韩亚洲欧美成人一区| 亚洲福利视频三区| 欧美成人在线免费观看| 亚洲淫性视频| 亚洲少妇最新在线视频| 亚洲伦理自拍| 亚洲美女黄网| 一个色综合导航| 一区二区三区日韩欧美| 9人人澡人人爽人人精品| 欧美sm重口味系列视频在线观看| 久久国产精品毛片| 久久成人亚洲| 免费在线看一区| 欧美成人资源网| 欧美插天视频在线播放| 欧美大色视频| 亚洲国产精品一区二区www| 亚洲国产精彩中文乱码av在线播放| 欧美成人免费在线观看| 欧美韩日视频| 亚洲三级影院| 亚洲一区二区高清视频| 亚洲综合国产| 久久精品水蜜桃av综合天堂| 9色精品在线| 亚洲一区视频| 久久精品人人做人人爽| 六月天综合网| 国产精品高潮在线| 国模吧视频一区| 91久久国产综合久久蜜月精品| 一区二区免费在线观看| 欧美在线免费视频| 久久综合狠狠| 99精品欧美一区| 欧美一区二区在线免费播放| 欧美成人精品一区二区| 欧美性感一类影片在线播放| 国产一区二区三区精品久久久| 在线观看av不卡| 亚洲福利国产| 亚洲专区一区| 男人的天堂亚洲在线| 亚洲毛片在线观看| 久久精品国产清高在天天线| 欧美一区免费| 欧美精品福利视频| 国产婷婷色综合av蜜臀av| 亚洲精品日韩欧美| 久久久噜久噜久久综合| 亚洲伦理在线免费看| 久久久久久自在自线| 欧美午夜精品久久久久久浪潮| 在线观看精品视频| 欧美与黑人午夜性猛交久久久| 欧美激情一区二区三区 | 欧美成人在线免费观看| 亚洲一区二区三区高清| 欧美第一黄色网| 国模 一区 二区 三区| 亚洲在线一区二区三区| 亚洲激情在线观看| 久久综合亚洲社区| 国产亚洲午夜| 欧美亚洲免费电影| 久久久久久久一区二区三区| 99国产精品久久久久久久久久| 麻豆91精品91久久久的内涵|