最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++11中模板隱式實(shí)例化與顯式實(shí)例化的定義詳解分析

 更新時(shí)間:2022年04月25日 08:38:59   作者:云飛揚(yáng)_Dylan  
實(shí)例化是為在程序中的函數(shù)模板本身并不會(huì)生成函數(shù)定義,它只是一個(gè)用于生成函數(shù)定義的方案。編譯器使用模板為特定類型生成函數(shù)定義時(shí),得到的是模板實(shí)例。這即是函數(shù)模板的實(shí)例化。而函數(shù)模板實(shí)例化又分為兩種類型:隱式實(shí)例化和顯式實(shí)例化

1. 隱式實(shí)例化

在代碼中實(shí)際使用模板類構(gòu)造對(duì)象或者調(diào)用模板函數(shù)時(shí),編譯器會(huì)根據(jù)調(diào)用者傳給模板的實(shí)參進(jìn)行模板類型推導(dǎo)然后對(duì)模板進(jìn)行實(shí)例化,此過程中的實(shí)例化即是隱式實(shí)例化。

template<typename T>
T add(T t1, T2)
{
    return t1 + t2;
}
template<typename T>
class Dylan
{
public:
    T m_data;
};
int main()
{
    int ret = add(3,4);//隱式實(shí)例化,int add<int>(int t1, int t2);
    Dylan<double> dylan;//隱式實(shí)例化
}

2. 顯式實(shí)例化聲明與定義

extern template int add<int>(int t1, int t2);//顯式實(shí)例化聲明
extern template class Dylan<int>;            //顯式實(shí)例化聲明
template int add<int>(int t1, int t2);       //顯式實(shí)例化定義
template class Dylan<int>;                   //顯式實(shí)例化定義

當(dāng)編譯器遇到顯式實(shí)例化聲明時(shí),表示實(shí)例化定義在程序的其他地方(相對(duì)于當(dāng)前cpp文件)即在其他某一個(gè)cpp文件中定義,因此不再按照模板進(jìn)行類型推導(dǎo)去生成隱式實(shí)例化定義。

當(dāng)編譯器遇到顯式實(shí)例化定義時(shí),根據(jù)定義所提供的模板實(shí)參去實(shí)例化模板,生成針對(duì)該模板實(shí)參的實(shí)例化定義。

3. 顯式實(shí)例化的用途

模板類、函數(shù)通常定義在頭文件中,這些頭文件會(huì)被很多cpp文件包含,在這些cpp文件中會(huì)多次使用這些模板,比如下面的例子:

//template.hpp
template<typename T>
class Dylan
{
public:
    T m_data;
};
//test1.cpp
#include "template.hpp"
Dylan<int> t1;
Dylan<int> t2;
//test2.cpp
#include "template.hpp"
Dylan<int> t3;
Dylan<int> t4;

在test1.cpp/test2.cpp 中多次實(shí)例化了Dylan<int>類,按說編譯完后的可執(zhí)行程序中會(huì)包含多份Dylan<T>的定義,然而實(shí)際上,整個(gè)程序中卻只有一份Dylan<T>的定義。這個(gè)處理是在編譯和鏈接過程中實(shí)現(xiàn)的,目前主流的實(shí)現(xiàn)模式有兩種:      

a. Borland模式

Borland模式通過在編譯器中加入與公共塊等效的代碼來解決模板實(shí)例化問題。在編譯時(shí),每個(gè)文件獨(dú)立編譯,遇到模板或者模板的實(shí)例化都不加選擇地直接編譯。在鏈接的時(shí)候?qū)⑺心繕?biāo)文件中的模板定義和實(shí)例化都收集起來,根據(jù)需要只保留一個(gè)。這種方法實(shí)現(xiàn)簡單,但因?yàn)槟0宕a被重復(fù)編譯,增加了編譯時(shí)間。在這種模式下,我們編寫代碼應(yīng)該盡量讓模板的所有定義都放入頭文件中,以確保模板能夠被順利地實(shí)例化。要支持此模式,編譯器廠商必須更換支持此模式的鏈接器。

b. Cfront模式

AT&T編譯器支持此模式,每個(gè)文件編譯時(shí),如果遇到模板定義和實(shí)例化都不直接編譯,而是將其存儲(chǔ)在模板存儲(chǔ)庫中(template repository)。模板存儲(chǔ)庫是一個(gè)自動(dòng)維護(hù)的存儲(chǔ)模板實(shí)例的地方。在鏈接時(shí),鏈接器再根據(jù)實(shí)際需要編譯出模板的實(shí)例化代碼。這種方法效率高,但實(shí)現(xiàn)復(fù)雜。在這種模式下,我們應(yīng)該盡量將非內(nèi)聯(lián)成員模板的定義分離到一個(gè)單獨(dú)的文件中,進(jìn)行單獨(dú)編譯。

在一個(gè)鏈接器支持Borland模式的編譯目標(biāo)(編譯后的可執(zhí)行文件)上,g++使用Borland模式解決實(shí)例化問題。比如ELF(Linux/GNU), Mac OS X, Microsoft windows, 否則,g++不支持上述兩種模式。

如何避免Borland模式的缺點(diǎn)?

上面我們說g++實(shí)現(xiàn)的是Borland 模式,由于我們?yōu)槊恳环輰?shí)例化生成代碼,這樣在大型程序中就有可能包含很多重復(fù)的實(shí)例化定義代碼,雖然鏈接階段,鏈接器會(huì)剔除這些重復(fù)的定義,但仍然會(huì)導(dǎo)致編譯過程中的目標(biāo)文件(或者共享庫文件)過于龐大。這時(shí)候,我們就可以通過C++11的模板顯式實(shí)例化的方法解決??聪旅娴拇a:

// template.hpp
template<typename T>
class Dylan
{
public:
    Dylan(T t);
    T m_data;
};
// template.cpp
#include "template.hpp"
template<typename T>
Dylan<T>::Dylan(T t)
{
    m_data = t;
}
template class Dylan<int>; //模板實(shí)例化定義
// main.cpp
#include "template.hpp"
extern template class Dylan<int>; //模板實(shí)例化聲明,告訴編譯器,此實(shí)例化在其他文件中定義
                                  //不需要根據(jù)模板定義生成實(shí)例化代碼  
int main()
{
    Dylan<int> dylan(3);//OK, 使用在template.cpp中的定義
    Dylan<float> dylan1(3.0);//error, 引發(fā)未定義錯(cuò)誤
}

   上面的代碼中,我們將模板類的具體定義放在template.cpp中,并且在template.cpp中通過顯式實(shí)例化定義語句具體化了Dylan<int>。在main.cpp中,我們通過顯式實(shí)例化聲明告訴編譯器,Dylan<int>將在其他文件中定義,不需要在本文件中根據(jù)template.hpp的類模板實(shí)例化Dylan<int>。

由于我們沒有針對(duì)Dylan<float>做顯式實(shí)例化的聲明和定義,因此Dylan<float> dylan(3.0)會(huì)根據(jù)template.hpp中的類模板定義進(jìn)行隱式實(shí)例化,然而構(gòu)造函數(shù)是在template.cpp文件中定義的,在template.hpp中找不到構(gòu)造函數(shù)的定義,因而報(bào)錯(cuò)。如果把構(gòu)造函數(shù)的定義挪回template.hpp,那Dylan<float>就能通過編譯了。

Note:在編譯中,如果指定-fno-implicit-templates,編譯器就會(huì)禁止隱式實(shí)例化,從而只使用顯式實(shí)例化。

參考文獻(xiàn):Template Instantiation (Using the GNU Compiler Collection (GCC))

到此這篇關(guān)于C++11中模板隱式實(shí)例化與顯式實(shí)例化的定義詳解分析的文章就介紹到這了,更多相關(guān)C++模板實(shí)例化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++類和對(duì)象實(shí)戰(zhàn)之Date類的實(shí)現(xiàn)方法

    C++類和對(duì)象實(shí)戰(zhàn)之Date類的實(shí)現(xiàn)方法

    C++ 標(biāo)準(zhǔn)庫沒有提供所謂的日期類型,C++ 繼承了C語言用于日期和時(shí)間操作的結(jié)構(gòu)和函數(shù),這篇文章主要給大家介紹了C++類和對(duì)象實(shí)戰(zhàn)之Date類的實(shí)現(xiàn)方法,需要的朋友可以參考下
    2021-12-12
  • C語言對(duì)結(jié)構(gòu)體數(shù)組按照某項(xiàng)規(guī)則進(jìn)行排序的實(shí)現(xiàn)過程探究

    C語言對(duì)結(jié)構(gòu)體數(shù)組按照某項(xiàng)規(guī)則進(jìn)行排序的實(shí)現(xiàn)過程探究

    這篇文章主要介紹了C語言對(duì)結(jié)構(gòu)體數(shù)組按照某項(xiàng)規(guī)則進(jìn)行排序的實(shí)現(xiàn)過程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-02-02
  • C++抽象基類講解

    C++抽象基類講解

    這篇文章主要介紹了C++抽象基類講解,象基類abstract base class簡稱ABC,C++實(shí)現(xiàn)繼承的時(shí)候,需要保證派生類和基類之間是一種is-a的關(guān)系。在大多數(shù)時(shí)刻,這樣的關(guān)系是沒有問題的,然而在一些特殊的情況可能會(huì)遇到問題,下面來看看文章的具體介紹吧
    2022-01-01
  • C 語言進(jìn)制之間的轉(zhuǎn)換

    C 語言進(jìn)制之間的轉(zhuǎn)換

    本篇文章主要介紹了C語言進(jìn)制之間的轉(zhuǎn)換,舉例說明并附圖片,幫助大家理解,希望對(duì)大家有所幫助
    2016-07-07
  • 詳解C標(biāo)準(zhǔn)庫堆內(nèi)存函數(shù)

    詳解C標(biāo)準(zhǔn)庫堆內(nèi)存函數(shù)

    在C/C++語言中,我們知道內(nèi)存分為這幾種:程序全局變量內(nèi)存、棧內(nèi)存、堆內(nèi)存。其中堆內(nèi)存就是通過malloc(new)來分配的內(nèi)存,本文我們來探討一下C標(biāo)準(zhǔn)庫堆內(nèi)存函數(shù)。
    2021-06-06
  • C++無鎖數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)示例詳解

    C++無鎖數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)示例詳解

    這篇文章主要為大家介紹了C++無鎖數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • C++實(shí)現(xiàn)哈夫曼樹簡單創(chuàng)建與遍歷的方法

    C++實(shí)現(xiàn)哈夫曼樹簡單創(chuàng)建與遍歷的方法

    這篇文章主要介紹了C++實(shí)現(xiàn)哈夫曼樹簡單創(chuàng)建與遍歷的方法,對(duì)于C++算法的學(xué)習(xí)來說不失為一個(gè)很好的借鑒實(shí)例,需要的朋友可以參考下
    2014-07-07
  • C++超詳細(xì)講解auto與nullptr的使用

    C++超詳細(xì)講解auto與nullptr的使用

    C++11提供了nullptr用來取代0或者NULL。在C++11之前,使用NULL為空指針賦初值,但NULL其實(shí)就是0,這時(shí)會(huì)把NULL當(dāng)成0來用;在C++11中,我們?cè)诼暶饕粋€(gè)變量或?qū)ο?,指定它的類型時(shí),可以不使用變量本身的類型而使用auto替代
    2022-05-05
  • C語言設(shè)計(jì)一個(gè)閃閃的圣誕樹

    C語言設(shè)計(jì)一個(gè)閃閃的圣誕樹

    本文使用C語言基礎(chǔ)知識(shí)在控制臺(tái)打印一個(gè)圣誕樹效果,真的很簡單哦,一起通過本文學(xué)習(xí)吧
    2016-12-12
  • C++之Qt5雙緩沖機(jī)制案例教程

    C++之Qt5雙緩沖機(jī)制案例教程

    這篇文章主要介紹了C++之Qt5雙緩沖機(jī)制案例教程,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07

最新評(píng)論

永兴县| 阳曲县| 三穗县| 喀喇| 舟曲县| 通山县| 隆德县| 博白县| 锦州市| 济南市| 棋牌| 永定县| 沿河| 泰顺县| 靖安县| 都兰县| 涞源县| 枣强县| 元谋县| 延安市| 湟源县| 昌乐县| 松滋市| 南和县| 福贡县| 普格县| 四平市| 额敏县| 兴义市| 泗水县| 新建县| 太保市| 越西县| 塔城市| 涡阳县| 正定县| 衡南县| 三江| 安义县| 巫山县| 察雅县|