无码av一区二区三区无码,在线观看老湿视频福利,日韩经典三级片,成 人色 网 站 欧美大片在线观看

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

2 引入模板,支持復(fù)雜類型

2023-03-06 15:05 作者:HC_0702  | 我要投稿

本項(xiàng)目GitHub: HuangCheng72/HCSTL: 我的STL實(shí)現(xiàn) (github.com): https://github.com/HuangCheng72/HCSTL

進(jìn)入正文。

我們?cè)谏弦黄呀?jīng)實(shí)現(xiàn)了只支持double類型的vector,那么問題來了,如果我們要實(shí)現(xiàn)支持C++全部?jī)?nèi)建類型的vector,該怎么做?我們可以考慮全都重新實(shí)現(xiàn)一遍,但這樣工作量顯然是太大了。所以我們需要C++的模板機(jī)制,把vector變成一個(gè)模板類。內(nèi)建類型,很好實(shí)現(xiàn),直接加上模板語(yǔ)句 template 開文本替換用 T (其實(shí)你自己可以指定任意名字,Tp,E什么的都行)全部替換一下double就行了:

但是問題來了,如果不是內(nèi)建類型的數(shù)據(jù)呢?比如用戶自己定義的類的對(duì)象這種數(shù)據(jù),它和內(nèi)建類型的數(shù)據(jù)有什么區(qū)別?

大家都上過C++課,也都應(yīng)該知道,類的對(duì)象是new出來的,而內(nèi)建類型的數(shù)據(jù)是可以不用new的(要是非要new那我也沒話說)。

而new一個(gè)類的對(duì)象,涉及了兩個(gè)操作:

  1. 申請(qǐng)一塊內(nèi)存空間,用來存放這個(gè)對(duì)象。

  2. 在這塊空間上根據(jù)參數(shù)輸入調(diào)用類相應(yīng)的構(gòu)造函數(shù),創(chuàng)建這個(gè)對(duì)象(初始化內(nèi)存空間的各個(gè)參數(shù))。

在我們上面的代碼中,我們可以看到,在vector的構(gòu)造函數(shù)和輔助函數(shù)中,我們都已經(jīng)申請(qǐng)了一段內(nèi)存空間(數(shù)組)用來存放vector中的數(shù)據(jù)。我們可以有兩種存放對(duì)象的方法:

  1. 將vector的數(shù)組所存放數(shù)據(jù)的類型改為T類型的指針,然后每個(gè)元素都是一個(gè)對(duì)象的指針,對(duì)象直接new出來。

  2. 將對(duì)象在vector的數(shù)組空間上創(chuàng)建。

為了與其他類型相統(tǒng)一,我們采用第二種方法,第一種方法如果感興趣的話可以自行嘗試,本教程對(duì)此不討論。

針對(duì)第二種方法,C++有一種運(yùn)算符,placement new(定位new),它的作用是在指定的內(nèi)存空間上創(chuàng)建對(duì)象,用法如下:

我們可以考慮采用定位new,來實(shí)現(xiàn)我們的方法,將對(duì)象在vector的數(shù)組空間上創(chuàng)建。

以帶參構(gòu)造函數(shù)為例:

那么就引出一個(gè)問題,我們?cè)撛趺磁袛嗄兀?/p>

我們自然而然可以想到,能不能實(shí)現(xiàn)一個(gè)判斷的函數(shù),這個(gè)函數(shù)輸入的參數(shù)是一種類型,返回一個(gè)bool值,如果輸入的參數(shù)是C++內(nèi)建類型,則返回true,如果輸入的參數(shù)不是C++內(nèi)建類型,則返回false,這樣是不是能夠解決問題了?

但是很遺憾,C++的函數(shù)參數(shù)不能是一種類型。當(dāng)然,如果你要將類型名字轉(zhuǎn)化為字符串,然后用字符串進(jìn)行判斷也是可以的,不過本教程對(duì)此不討論。

STL 對(duì)此采取的方法是類型萃取(type_traits),它的意義就是將類型的信息提取出來,可以通過一個(gè)判斷機(jī)制進(jìn)行判斷,達(dá)到我們的目的。類型萃取的實(shí)現(xiàn)采用了模板特化的思路。

在這里需要介紹一下POD類型:

POD(Plain Old Data)類型,指的是C++的內(nèi)建數(shù)據(jù)類型,還有原生指針和C風(fēng)格的結(jié)構(gòu)體聯(lián)合體等。標(biāo)準(zhǔn)的定義是:能用C的memcpy()等函數(shù)進(jìn)行操作 的類、結(jié)構(gòu)體或聯(lián)合體。POD類型有以下標(biāo)準(zhǔn):

  1. 沒有用戶自定義的構(gòu)造函數(shù)、析構(gòu)函數(shù)、拷貝賦值運(yùn)算符;

  2. 沒有虛函數(shù)和虛基類;

  3. 所有非靜態(tài)成員都是public;

  4. 所有非靜態(tài)成員都是POD類型;

  5. 沒有繼承或只繼承了POD類型。

POD類型和復(fù)雜數(shù)據(jù)類型最大的區(qū)別是四個(gè)方面:構(gòu)造(默認(rèn)構(gòu)造器)、析構(gòu)、賦值、復(fù)制(拷貝構(gòu)造器),即default_constructor,destructor,assignment_operator,copy_constructor。 復(fù)雜數(shù)據(jù)類型先天缺少這四樣(編譯器給它加上的不算),而可以認(rèn)為POD類型是先天具備或者 根本不用考慮 這四樣。

請(qǐng)新建一個(gè)頭文件為 type_traits.h ,在這個(gè)文件中實(shí)現(xiàn)類型萃取。

首先用兩個(gè)空結(jié)構(gòu)體表示true和false的結(jié)果(不用bool類型的原因是因?yàn)榭战Y(jié)構(gòu)體不占用內(nèi)存空間,bool變量還占用1字節(jié)空間):

然后利用C++的模板參數(shù)特化,將這兩個(gè)結(jié)構(gòu)體轉(zhuǎn)化為bool值可以用于判斷。

這是類型萃取的模板類:

這是針對(duì)內(nèi)建類型的特化實(shí)現(xiàn):

類型萃取這部分使用結(jié)構(gòu)體模板實(shí)現(xiàn),最大的好處是空模板不占用內(nèi)存空間(如果使用bool變量必然要占用至少一個(gè)字節(jié)的內(nèi)存空間),同時(shí)結(jié)構(gòu)體類型還可以作為模板參數(shù)傳遞,還有就是C風(fēng)格結(jié)構(gòu)體也是POD,這樣就不用管構(gòu)造和析構(gòu)的事情了。

所以,通過類型萃取,我們就可以寫我們的判斷條件了,還是以之前的帶參構(gòu)造函數(shù)為例,可以寫成:

因此,我們可以實(shí)現(xiàn)支持POD和非POD(non-POD)類型數(shù)據(jù)的vector了。

修改main.cpp,嘗試運(yùn)行一下non-POD類型的簡(jiǎn)單測(cè)試:

但是我們會(huì)發(fā)現(xiàn)運(yùn)行不了。我這里的IDE報(bào)錯(cuò)為:

通過查詢,該錯(cuò)誤代碼 0xC0000374 的含義為 A heap has been corrupted ,即堆內(nèi)存損壞。

debug發(fā)現(xiàn),問題出在輔助函數(shù)這里。

這是怎么回事呢?

分析代碼上下文我們發(fā)現(xiàn)了一個(gè)問題。

這就出現(xiàn)了歧義,編譯器不知道你要銷毀的是到底是哪個(gè),貿(mào)然銷毀導(dǎo)致堆內(nèi)存損壞。這個(gè)問題在析構(gòu)函數(shù)中也是一樣存在的。

但是我們暫時(shí)沒有好的解決方法,所以先擱置這個(gè)問題,加一個(gè)判斷,先run起來再說

run起來,可以看到main.cpp中我們的簡(jiǎn)單測(cè)試順利過關(guān)。

歡迎訪問本項(xiàng)目的GitHub倉(cāng)庫(kù),如果對(duì)您有幫助,麻煩給項(xiàng)目一個(gè)star,謝謝!

HuangCheng72/HCSTL: 我的STL實(shí)現(xiàn) (github.com): https://github.com/HuangCheng72/HCSTL

2 引入模板,支持復(fù)雜類型的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
客服| 牙克石市| 溧阳市| 阿瓦提县| 四川省| 卢氏县| 兴隆县| 长宁县| 青浦区| 岑溪市| 张家口市| 新邵县| 花莲县| 禹城市| 澄城县| 静乐县| 安庆市| 南京市| 鲁甸县| 盐亭县| 九龙城区| 建德市| 南充市| 南投市| 晋中市| 武功县| 漠河县| 三都| 大石桥市| 乐昌市| 民勤县| 诏安县| 溧阳市| 上林县| 金门县| 德格县| 灵川县| 黎平县| 遵义县| 太谷县| 巴楚县|