亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

不要被C++(自動生成規則)所蒙騙

2020-01-26 16:22:34
字體:
來源:轉載
供稿:網友

C++對象可以使用兩種方式進行創建:構造函數和復制構造函數。假如我們定義了類A,并使用它創建對象。

復制代碼 代碼如下:

A a,b;
A c=a;
A d(b);

對象a和b使用編譯器提供的默認構造函數A::A()創建出來,我們稱這種創建方式為對象的定義(包含聲明的含義)。對象c和d則是使用已有的對象,通過編譯器提供的復制構造函數A::A(const A&)創建,我們稱這種創建方式為對象的初始化(包含定義和聲明的含義)。

可能不少人會把對象的初始化和對象的賦值混淆,比如。

復制代碼 代碼如下:

c=d;

這里把對象d賦值給對象c并非創建新的對象,它不會調用任何構造函數。編譯器默認提供的賦值運算符重載函數const A&operator=(const A&)為該語句提供支持。

編譯器除了提供默認構造函數、復制構造函數和賦值運算符重載函數之外,有可能還為我們提供了析構函數A::~A(),但是這里的析構函數并不是virtual的(相信會有童鞋忘記這一點)。

這些基礎的語法對學習過C++的人或許并不陌生,我們自從學習了面向對象C++后,一直都知道編譯器為我們提供了這樣的便利條件。經過多年的編程實踐和體驗,我們絕對相信編譯器的確為我們做了這些工作,因為我們沒有遇到過任何問題。甚至我們腦子中會默認形成一個概念――即使我定義了一個空類(類內什么都沒有),編譯器依然會“乖乖的”為我們生成上邊所說的四個函數。

如果你真的形成了這種觀念的話,那么恭喜你,因為你已經將C++基本規則運用的十分熟練了。同時遺憾的是你我都看到了冰山一角,編譯器的工作方式遠不像我們使用它的那樣。讀者可能會疑問,難道編譯器沒有生成這些函數嗎?答:要看你類的定義。那么編譯器到底如何生成這些函數呢?和我一樣又好奇心的人都想一探究竟,而這些內容在《Inside The C++ Object Model》被詮釋的比較徹底。筆者也通過“借花獻佛”的方式將該書所描述的對象構造的內幕結合個人的理解和大家一起分享。

首先我們從最簡單的談起,編譯器為類生成構造函數了嗎?如果按照上邊描述的例子,只有一個空的類定義的話,我們可以肯定的說――沒有。對編譯器這樣的做法,我們不必感到驚訝。試想一個空的類――沒有數據成員,沒有成員函數,即使生成了構造函數又能做什么呢?即便是生成了,也只是一個空構造函數而已。

復制代碼 代碼如下:

A(){}

它什么也做不了,也什么都不必做。更“悲劇”,它的出現不僅沒有任何積極意義,還會為編譯器和程序運行增加完全不必要的函數調用負擔。

既然如此,我們讓這個類再復雜一點,我們為它增加數據成員和成員函數,比如下邊這段代碼(我們記它為例子1)。

復制代碼 代碼如下:

class A
{
public:
int var;
void fun(){}
};

即便如此,結果還是和上邊的一樣,不生成構造函數!因為沒有任何理由對var初始化,況且編譯器也不知道用什么值給它初始化。

果然,在主函數內定義對象a后,沒有任何構造函數被調用。

有人可能會說用0初始化不行嗎?這只是我們的“一廂情愿”而已。一個沒有初始化的變量本身的值就可以是不確定的,何必要生成一個沒有任何意義的初始化為0的語句呢。

編譯器到底怎樣才能生成構造函數呢?!或許你和我一樣有點“抓狂”了。不過現在還不是絕望的時候,因為編譯器需要我們給它一個“正當的理由”生成構造函數。有四個正當的理由,讓編譯器不得不生成構造函數,這里一一介紹。

首先,我們修改一下var的類型。這里假設它不是內置類型int,而是一個定義好的類B。

B var;

修改一下數據成員的類型為自定義類型能影響編譯器的抉擇嗎?答:可能。這要看類B有沒有定義構造函數。讀者可能有點明白了,是的,如果B沒有定義構造函數(和這里的A一個樣子),那么編譯器仍然沒有理由生成構造函數――為B初始化什么呢?反之,B一旦定義了默認構造函數B::B(),即便它是空的,編譯器就不得不為A創建默認構造函數了(這里不考慮編譯器的深度優化)。因為A的對象需要用B的默認構造函數初始化它自己的成員var,雖然B的構造函數什么也沒做。因為編譯器不能假定B的構造函數做了什么樣的操作(極端一點:萬一修改了一個全局變量了呢?),因此編譯器有絕對的必要生成A的構造函數,保證B類型的數據成員的構造函數正常執行。

轉到編譯器為A生成的構造函數處,我們發現了B的構造函數被調用的語句(選中行)。

當然,如果B提供了構造函數,但不是默認的構造函數,那么必須要程序員介入為var初始化,否則編譯器就不客氣了――error!

因此,編譯器生成默認構造函數的第一個正當理由是――類內數據成員是對象,并且該對象的類提供了一個默認構造函數。

現在,我們回到例子1,這里我們不修改var的類型,而是讓A繼承于另一個類C。

復制代碼 代碼如下:

class A:public C

我們都知道,在C++構造函數初始化語法中,構造函數會先初始化基類C,再初始化自身的數據成員或者對象。因此,這里的問題和對象成員var類似。如果基類C沒有提供任何構造函數,那么編譯器仍然不提供A的默認構造函數。如果C提供了默認構造函數,結果和前邊類似。

結果不出所料,編譯器為A生成了構造函數,并且調用了基類C定義的默認構造函數。同樣,若C沒有提供默認默認構造函數,而提供了其他構造函數,編譯是無法通過的。

這也是編譯器生成默認構造函數的第二個正當理由――類的基類提供了默認的構造函數。

我們再次回到例子1,這次我們修改成員函數fun。

復制代碼 代碼如下:

virtual void fun(){}

我們把類A的成員函數fun修改為虛函數,再次看看是否產生了默認構造函數。

這次編譯器“毫不客氣”的為A生成了默認構造函數,雖然它沒有調用任何其他的構造函數!這是什么原因呢?原來,C++為了實現多態機制,需要為類維護一個虛函數表(vftable),而每個該類的對象都保存一個指向該虛函數表的一個指針(一般保存在對象最開始的四個四節處,多態機制的實現這里暫不介紹)。編譯器為A生成構造函數,其實不為別的,就為了保證它定義的對象都要正常初始化這個虛函數表的指針(vfptr)!

好了,因此我們得出編譯器生成默認構造函數的第三個正當理由――類內定義了虛函數。這里可能還涉及一個更復雜點的情況:類內本身沒有定義虛函數,但是繼承了基類的虛函數。其實按照上述的原則,我們可以推理如下:基類既然定義了虛函數,那么基類本身就需要生成默認構造函數初始化它本身的虛函數表指針。而基類一旦產生了默認構造函數,派生類就需要產生默認構造函數調用它。同時,如果讀者對多態機制了解清除的話,派生類在生成的默認構造函數內還會初始化一次這個虛函數表指針的。

最后,我們再次回到例子1,這次仍然讓A繼承于C,但是這次C是一個空類――什么都沒有,也不會自動生成默認構造函數。但是A繼承C的方式要變化一下。

復制代碼 代碼如下:

class A:public virtual C

A虛繼承于C,這次又有什么不同呢?

這次編譯器也生成了A的構造函數,并且初始化過程和虛函數時有點類似。細心觀察下發現,這次構造函數也初始化了一張表――vbtable。了解虛繼承機制的讀者應該不會陌生,這張表叫虛基類表,它記錄了類繼承的所有的虛基類子對象在本類定義的對象內的偏移位置(至于虛繼承機制的實現,我們以后詳細探討)。為了保證虛繼承機制的正確工作,對象必須在初始化階段維護一個指向該表的一個指針,稱為虛表指針(vbptr)。編譯器因為它提供A的默認構造函數的理由和虛函數時類似。

這樣,我們得出編譯器生成默認構造函數的第四個正當理由――類使用了虛繼承

到這里,我們把編譯器為類生成默認構造函數的正當理由闡述完畢,相信大家應該對構造函數的生成時機有了一個大致的認識。這四種“正當理由”其實是編譯器不得不為類生成默認構造函數的理由,《Inside The C++ Object Model》里稱這種理由為nontrival的(候sir翻譯的很別扭,所以怎么翻譯隨你啦)。除了這四種情況外,編譯器稱為trival的,也就是沒有必要為類生成默認構造函數。這里討論的構造函數生成準則的內容是寫進C++Standard的,如此看來標準就是“貼合正常思維”的一套準則(簡單YY一下),其實本就是這樣,編譯器不應該為了一致化做一些沒有必要的工作。

通過對默認構造函數的討論,相信大家對復制構造函數、賦值運算符重載函數、析構函數的生成時機應該可以自動擴展了。沒錯,它們遵循著一個最根本的原則:只有編譯器不得不為這個類生成函數的時候(nontrival),編譯器才會真正的生成它。

因此,正如標題所說,我們不要被C++語法中所描述的那些條條框框所“蒙騙”了。的確,相信這些生成規則不會對我們的編程帶來多大的影響(不會產生錯誤),但是只有了解它們的背后操作,我們才知道編譯器究竟為我們做了什么,我們才知道如何使用C++才能讓它變得更有效率――比如消除不必要的構造和虛擬機制等(如果可以的話)。相信本文對C++自動生成的內容的描述讓不少人認清對象構造函數產生的前因后果,希望本文對你有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美精品九九久久| 隔壁老王国产在线精品| 国产精品久久久久久久久久99| 57pao国产精品一区| 国产亚洲欧洲高清一区| 在线电影欧美日韩一区二区私密| 成人久久一区二区三区| 精品中文字幕久久久久久| 久久综合久中文字幕青草| 少妇激情综合网| 欧美理论电影在线观看| 精品视频在线播放色网色视频| 国产美女久久精品香蕉69| 中文综合在线观看| 在线看片第一页欧美| 久久免费国产精品1| 欧美男插女视频| 久久91亚洲人成电影网站| 亚洲国产精品人久久电影| 日韩在线视频一区| 国产精品男人爽免费视频1| 欧美二区乱c黑人| 国产精品影院在线观看| 久久躁狠狠躁夜夜爽| 日日骚av一区| 欧美贵妇videos办公室| 日本成人在线视频网址| 狠狠躁夜夜躁人人爽超碰91| 国产丝袜一区视频在线观看| 国产精品日韩在线| 欧美成人免费va影院高清| 亚洲国产精品专区久久| 欧美在线视频播放| 国产一区二区三区在线观看视频| 777午夜精品福利在线观看| 欧美激情精品久久久久久免费印度| 黄色成人在线免费| 国产精品美女视频网站| 欧美怡春院一区二区三区| 亚洲精品国产拍免费91在线| 国产欧美日韩精品在线观看| 国模精品视频一区二区| 久久精品国产96久久久香蕉| 欧美丝袜美女中出在线| 亚洲图片欧美午夜| 成人国产精品久久久| 2019中文字幕在线免费观看| 亚洲性视频网址| 国产成人精品av在线| 亚洲国产成人精品久久久国产成人一区| 亚洲精品一区二区在线| 欧美极度另类性三渗透| 日韩av综合网站| 日本视频久久久| 欧美成人网在线| 亚洲视频专区在线| 日韩欧美视频一区二区三区| 欧美日韩国产精品一区二区三区四区| 亚洲精品国产精品乱码不99按摩| 国产亚洲a∨片在线观看| 国产成人一区二区在线| 97在线观看免费高清| 97视频国产在线| 国产999精品久久久影片官网| 日本成人免费在线| 欧美俄罗斯性视频| 久久影视三级福利片| 国产日韩欧美日韩大片| 日韩高清欧美高清| 国产精品九九九| 久久久女女女女999久久| 久久免费视频观看| 欧美日产国产成人免费图片| 欧美日韩亚洲成人| 97免费在线视频| 91精品免费久久久久久久久| 欧美一区亚洲一区| 97色在线观看免费视频| 欧美成人亚洲成人日韩成人| 欧美日韩一区免费| 自拍偷拍亚洲区| 最近中文字幕mv在线一区二区三区四区| 97精品国产91久久久久久| 欧美大片第1页| 日本亚洲欧洲色| xxxxx成人.com| 国产精品h片在线播放| 久久久久久久一区二区三区| 欧美日韩国产一区中文午夜| 91情侣偷在线精品国产| 98精品国产自产在线观看| 亚洲精品欧美日韩| 欧美激情视频免费观看| 国产成人精品一区二区三区| 欧美成人一区在线| 国产一区二区欧美日韩| 欧美成人免费播放| 久久的精品视频| 在线观看日韩www视频免费| 亚洲变态欧美另类捆绑| 精品露脸国产偷人在视频| 九九热视频这里只有精品| 国产精品亚洲美女av网站| 中文字幕日韩在线视频| 欧美精品一区二区三区国产精品| 日韩免费看的电影电视剧大全| 成人精品福利视频| 97色在线播放视频| 中文字幕日韩在线观看| 不卡av电影在线观看| 国产欧美日韩丝袜精品一区| 日韩精品中文字幕久久臀| 中文字幕在线国产精品| 亚洲国产高清福利视频| 中文字幕亚洲综合| 国产成人高清激情视频在线观看| 精品久久久香蕉免费精品视频| 日韩免费在线免费观看| 一区二区福利视频| 欧美成人精品在线视频| 91精品久久久久久久久久入口| 91九色蝌蚪国产| 日韩资源在线观看| 亚洲欧美日韩精品久久| xvideos亚洲人网站| 亚洲a∨日韩av高清在线观看| 国产精品久久久久久av福利软件| 久久久久久一区二区三区| 国产精品羞羞答答| 成人美女免费网站视频| 成人中文字幕+乱码+中文字幕| 精品国产美女在线| 欧美日韩美女在线观看| 人人爽久久涩噜噜噜网站| 欧美最顶级的aⅴ艳星| 精品久久久国产| 亚洲一区制服诱惑| 久久人人爽人人爽人人片亚洲| 91国内免费在线视频| 亚洲一区亚洲二区| 亚洲天堂男人天堂| 91国偷自产一区二区三区的观看方式| 78m国产成人精品视频| 欧美丰满少妇xxxxx做受| 海角国产乱辈乱精品视频| 国产在线观看精品一区二区三区| 国产精品黄页免费高清在线观看| 成人免费在线视频网站| 久久男人av资源网站| 国产成人高清激情视频在线观看| 国产福利精品av综合导导航| xx视频.9999.com| 欧美一区二粉嫩精品国产一线天| 国产欧美日韩高清| xxx欧美精品| 国产69精品久久久久久| 午夜精品国产精品大乳美女| 精品自拍视频在线观看| 日韩中文综合网| 少妇久久久久久| 97免费视频在线| 亚洲欧美日韩久久久久久| 奇米一区二区三区四区久久| 国产97在线播放|