国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

做美食的網(wǎng)站有那一些韓國網(wǎng)站

做美食的網(wǎng)站有那一些,韓國網(wǎng)站,蘇州商城網(wǎng)站制作,合肥做網(wǎng)站便宜前言: 本篇內(nèi)容為前面的補(bǔ)充,介紹了我們使用類時需要注意些什么以及一些編譯器的優(yōu)化,可能有些理解不到位或者錯誤,請斧正。 目錄 前言: 1.再談構(gòu)造函數(shù) 2.(c98)隱式類型轉(zhuǎn)換中的編譯器的優(yōu)…

前言:

本篇內(nèi)容為前面的補(bǔ)充,介紹了我們使用類時需要注意些什么以及一些編譯器的優(yōu)化,可能有些理解不到位或者錯誤,請斧正。

目錄

前言:

1.再談構(gòu)造函數(shù)

2.(c++98)隱式類型轉(zhuǎn)換中的編譯器的優(yōu)化

3.explicit關(guān)鍵字

4.static成員

5.匿名對象

6.友元函數(shù)

7.內(nèi)部類

8.編譯器的一些場上的優(yōu)化

總結(jié):

若有歧義,請指出,感謝閱讀!


1.再談構(gòu)造函數(shù)

我們在構(gòu)造函數(shù)體中,給成員變量賦值能叫做成員變量的初始化嗎?并不可以,這種行為只是給成員變量賦初值,在函數(shù)體中,我們可以多次賦值,而初始化只能初始化一次。

那該如何初始化呢?

使用初始化列表。以一個冒號開始,接著是一個以逗號分割的數(shù)據(jù)成員列表,每個成員變量的后面跟一個放在括號中的初始值表達(dá)式。

class Date
{
public:Date(int year, int month, int day):_year(year),_month(month),_day(day){}private:int _year;int _month;int _day;
};

?那像const這樣的必須在定義位置的初始化的,放在成員變量里面該怎么初始化呢?

可以給缺省值,但不是初始化:

class A
{
public:A():_x(1){_a1++;}private:int _a1 = 1;int _a2 = 2;const int _x;//可以給缺省值,但不是初始化};

另外,缺省值也會在初始化列表進(jìn)行初始化:

如上圖我們可以看到, _a1的結(jié)果是2,雖然沒有在初始化列表中顯示的初始化,但是還是會走初始化列表初始化;其次_a2的結(jié)果是0,雖然_a2的缺省值是2,但是在初始化列表中顯示的初始化為了1,所以再--就是0。而對于即不給缺省值也不給初始化的普通成員變量,經(jīng)過測試,那就是隨機(jī)值。

對于成員變量是引用的與成員變量是自定義類型的:

class B
{
public:B(int b):_b(0){cout << "B()" << endl;}private:int _b;
};class A
{
public:A():_x(1),_ref(_a1),_bb(0){_a1++;}private:int _a1 = 1;int _a2 = 2;int& _ref;B _bb;const int _x;//可以給缺省值,但不是初始化};

成員變量是引用的,跟const一樣,本身引用就是要在定義的位置初始化,所以我們可以給缺省值,或者要在初始化列表初始化。

對于自定義類型的成員變量,_bb會去調(diào)用它的構(gòu)造函數(shù)初始化嗎?經(jīng)過我的測試,_bb這個自定義類型的成員變量,如果不在A中的初始化列表初始化,就要去調(diào)用它的構(gòu)造函數(shù),但是一定要確保B中的構(gòu)造函數(shù)一定是默認(rèn)的,也就是說必須是全缺省的或者是不寫編譯器自動生成的。而上面的代碼中B中的構(gòu)造函數(shù)不是默認(rèn)的構(gòu)造函數(shù),所以我們?nèi)绻贏的類中不對_bb進(jìn)行初始化列表的初始化,就會報錯。

再看一個例子:

?注釋部分的構(gòu)造函數(shù)可以,對兩個自定義類型的成員進(jìn)行了初始化列表的初始化,而內(nèi)置類型由于沒有顯示的寫就使用了缺省值,所以可以;如果Stack這個自定義類型中的構(gòu)造函數(shù)是默認(rèn)的,什么也沒寫的構(gòu)造函數(shù)也是可以的,對于自定義類型初始化去調(diào)用它的默認(rèn)構(gòu)造函數(shù),內(nèi)置類型的初始化由于沒有顯示的寫就使用它的缺省值。

其次還需要注意一個點(diǎn):

class A1
{
public:A1(int a):_a1(a),_a2(_a1){}void Print(){cout << _a1 << " " << _a2 << endl;}private:int _a2;//聲明的次序就是在初始化列表中的初始化的順序int _a1;
};int main(){//A aa;A1 aa(1);aa.Print();return 0;
}

上面的結(jié)果應(yīng)該是什么?結(jié)果是輸出1和隨機(jī)值。

這是因?yàn)槌蓡T變量在類中的聲明次序就是其在初始化列表中的初始化順序,與其在初始化列表中的先后次序無關(guān)。

總結(jié):

首先不管在初始化列表中顯示的寫沒寫初始化,都會在初始化的列表中走一遍。

其次記住一個原則:給初始化就在初始化列表中給初始化。

2.(c++98)隱式類型轉(zhuǎn)換中的編譯器的優(yōu)化

class A
{
public:A(int a): _a1(a){cout << "A(int a)" << endl;}A(const A& aa):_a1(aa._a1){cout << "A(const A& aa)" << endl;}private:int _a1;
};int main(){A aa1(1);//構(gòu)造函數(shù)A aa2 = 1;//隱式類型轉(zhuǎn)換return 0;
}

根據(jù)我們之前的隱式類型轉(zhuǎn)換的知識,我們可以知道這里對aa2這個對象賦值就是在進(jìn)行隱式類型轉(zhuǎn)換:首先1先構(gòu)造一個臨時對象,這個臨時對象再拷貝給aa2,所以會去調(diào)用拷貝構(gòu)造(注意拷貝構(gòu)造也是構(gòu)造,所以也有初始化列表)。

但是我們看到結(jié)果不是這樣的:

為什么呢?這就是編譯器所做的優(yōu)化,因?yàn)榫幾g器覺得自定義類型的這種初始化寫起來還要調(diào)用拷貝構(gòu)造,所以直接就優(yōu)化了,直接就優(yōu)化為了一步構(gòu)造,1直接構(gòu)造aa2。(注意這里的優(yōu)化只限定于c++98的單參數(shù)的構(gòu)造)

而對于這一種,編譯器還能這樣優(yōu)化嗎?答案是不能的,因?yàn)槲覀冎?#xff0c;10先構(gòu)造出一個A類型的臨時變量,而這個臨時變量又具有常性且ref是這個臨時變量的別名,所以需要加上const,而就是由于這個臨時變量具有常性,編譯器在這里就不會優(yōu)化掉這個臨時變量,所以10就沒法直接構(gòu)造ref了,而是先構(gòu)造這個臨時變量(這里使用的vs2022的編譯器發(fā)現(xiàn)也沒有調(diào)用拷貝構(gòu)造,可能是編譯器做的更極端了,也優(yōu)化了,但是我們知道其后的原來即可)。

3.explicit關(guān)鍵字

explicit的引入就是為了防止隱式類型轉(zhuǎn)換,這里加上了explicit,?A aa2=1和const A& ref=10的隱式類型轉(zhuǎn)換就沒有了,就編不過了。

但是上面的隱式類型轉(zhuǎn)換都是對于單參數(shù)的構(gòu)造,對于多參數(shù)的構(gòu)造,c++11可以使用多參數(shù)的構(gòu)造來進(jìn)行隱式類型轉(zhuǎn)換:

其實(shí)也都是先調(diào)用構(gòu)造,然后再進(jìn)行隱式類型轉(zhuǎn)換,再經(jīng)過編譯器的優(yōu)化,?會節(jié)省一次隱式類型轉(zhuǎn)換產(chǎn)生的拷貝。

同樣的,如果不想使用隱式類型轉(zhuǎn)換,就在構(gòu)造函數(shù)上加上explicit,防止構(gòu)造函數(shù)的隱式類型轉(zhuǎn)換,這時A aa(1,1)這樣需要隱式類型轉(zhuǎn)換的就編不過了。

如果想使用隱式類型轉(zhuǎn)換,讓編譯器進(jìn)行優(yōu)化,節(jié)省一次拷貝,就可以不加explicit。?

4.static成員

我們將聲明為static的類成員稱為類的靜態(tài)成員,用static修飾的成員變量,稱為靜態(tài)成員變量;用static修飾的成員函數(shù),稱之為靜態(tài)成員函數(shù)。注意的是,靜態(tài)成員函數(shù)沒有this指針,靜態(tài)成員變量在類中聲明,在類外進(jìn)行初始化。

統(tǒng)計程序中創(chuàng)建出了多少個類對象:

class A
{
public:A(int a = 0){cout << "構(gòu)造" << endl;}A(const A& aa){cout << "拷貝構(gòu)造" << endl;++count;}static int GetCount()//沒有this指針{return count;//static函數(shù)沒有this指針,訪問不到成員count,只能讀不能寫}private:static int count;//聲明,屬于所有對象,屬于整個類};int A::count = 0;//定義初始化
void func(A a)
{}int main()
{A aa1;//調(diào)用構(gòu)造A aa2(aa1);//調(diào)用拷貝構(gòu)造func(aa1);//函數(shù)傳參,且參數(shù)是A類型的,所以調(diào)用拷貝構(gòu)造A aa3 = 1;//隱式類型轉(zhuǎn)換,經(jīng)過編譯器的優(yōu)化,優(yōu)化掉了拷貝構(gòu)造,只有構(gòu)造A aa4[10];//調(diào)用10次構(gòu)造cout << aa3.GetCount() << endl;//如果GetCount是個static修飾的,只能接受返回的count,不能改//類中的靜態(tài)成員也受訪問限定符的限制,如果我們不讓靜態(tài)成員count設(shè)為私有,如何訪問count?//A::count;//aa2.count或者aa3.count      count屬于所有對象//A* ptr=nullptr;ptr->count   這里不會去解引用,會直接去靜態(tài)區(qū)中找return 0;
}

?首先上面代碼需要注意的是,GetCount是一個靜態(tài)成員函數(shù),所以訪問它可以通過對象訪問即aa3.GetCount(),或者指定內(nèi)域訪問,A::GetCount(),但是由于靜態(tài)成員函數(shù)沒有this指針,所以函數(shù)內(nèi)不能訪問非靜態(tài)成員變量(這里返回count就是因?yàn)閏ount是個靜態(tài)成員變量,換成是普通的變量就不行了):

其次類中的靜態(tài)成員也是受類的訪問限定符的限制的,像這里count為私有,雖然是靜態(tài)的全局的變量,但是在類外面還是訪問不到的。

如果我們不將count設(shè)為私有,那怎么訪問這個靜態(tài)成員變量呢?

1.A::count? 直接指定內(nèi)域訪問

2.aa2.count或者aa3.count? ? 因?yàn)閟tatic成員是屬于所有對象的,所以可以

3.A* ptr=nullptr;ptr->count? ? 這里不會解引用,直接去靜態(tài)區(qū)找

同時我們上方的代碼也復(fù)習(xí)之前的知識:

分析結(jié)果:

前兩個分別調(diào)用構(gòu)造與拷貝構(gòu)造,沒什么說的;第三個是函數(shù)傳參,由于參數(shù)也是A,也就是類類型的,所以會調(diào)用拷貝構(gòu)造;然后是下面的隱式類型轉(zhuǎn)換,編譯器優(yōu)化掉了拷貝,直接就是構(gòu)造;然后可以看到如果自定義對象是數(shù)組,可以看到調(diào)用了10次。

總結(jié):

5.匿名對象

當(dāng)我們需要調(diào)用某個類的成員函數(shù)時需要先創(chuàng)建一個對象,所以我們引入了一個匿名對象,可以直接不創(chuàng)建對象直接去調(diào)用,寫法為:類名()

通過析構(gòu)函數(shù)可知,匿名對象的周期只在它出現(xiàn)的這一行,到下一行就會銷毀。

返回值也可以使用匿名對象,更加簡潔。

6.友元函數(shù)

友元函數(shù)在我們之前提到過,現(xiàn)在再來細(xì)看一下。

7.內(nèi)部類

內(nèi)部類c++很少用,隔壁Java常用。

首先,如果B這個類在A中是公有的,可以直接在外面指明內(nèi)域訪問例如A::B bb;

其次,如果B是私有的,那就不能通過A來訪問了,所以B這個內(nèi)部類既受A的類域的

限制(因?yàn)锽為公有在外面需要指定在A的內(nèi)域),又受到A的訪問限定符的限制

然后,B這個內(nèi)部類天生就是A的友元,所以可以通過內(nèi)部類訪問外部類的成員(靜態(tài)的也可以)

補(bǔ)充:一個類里面,公有可以訪問私有

總結(jié):

8.編譯器的一些場上的優(yōu)化

首先先來分析3個優(yōu)化:

class A
{
public:A(int a = 0){cout << "構(gòu)造" << endl;}A(const A& a){cout << "拷貝構(gòu)造" << endl;}~A(){cout << "~A" << endl;}
};void func1(A aa)
{}void  func2(A& aa)
{}A func3()
{return A();
}int main()
{A aa1 = 1;func1(aa1);func1(2);func1(A(3));return 0;
}

第一個就是隱式類型轉(zhuǎn)換編譯器會將隱式類型轉(zhuǎn)換產(chǎn)生的拷貝優(yōu)化掉,所以就只有一個構(gòu)造。

第二個是傳參調(diào)用拷貝構(gòu)造,但是這個拷貝構(gòu)造不會被優(yōu)化(大部分情況下只有c++98中的那個單參數(shù)構(gòu)造和c++11的多參數(shù)構(gòu)造會優(yōu)化),但是可以使用傳引用傳參來減少拷貝。由于拷貝構(gòu)造產(chǎn)生了臨時變量,所以在func1函數(shù)結(jié)束時,會調(diào)用析構(gòu)銷毀這個臨時變量。

第三個與第四個也都是傳參調(diào)用拷貝構(gòu)造,但是結(jié)果發(fā)現(xiàn),拷貝構(gòu)造被優(yōu)化為了構(gòu)造?!理想的結(jié)果不應(yīng)該是拷貝構(gòu)造,然后跟析構(gòu)嗎???當(dāng)時我也疑惑了好久,其實(shí)這是因?yàn)榫幾g器的處理,在我的vs2022的編譯器下,可能由于編譯器太新,優(yōu)化的比較極端,編譯器看到你func1函數(shù)什么也沒寫,干嘛要在拷貝構(gòu)造一次,干脆直接就優(yōu)化為了拿形參構(gòu)造實(shí)參,可以看到構(gòu)造后緊跟的就是析構(gòu),這也表明還是存在拷貝產(chǎn)生的臨時變量需要銷毀。

最后主函數(shù)結(jié)束aa1銷毀調(diào)用析構(gòu)。

另外,如果我們使用func2的傳引用傳參,后兩個傳參會直接報錯,因?yàn)樗鼈兪桥R時變量,使用引用后,傳過去后函數(shù)作用域銷毀,這個變量就找不到了;而aa1的作用域在main函數(shù)中,盡管fun2的函數(shù)結(jié)束,但是還是能找到aa1。

再看一種優(yōu)化:

在這個場景下,?A aa先構(gòu)造,返回aa再調(diào)用拷貝構(gòu)造(因?yàn)闆]有創(chuàng)造對象,所以這個拷貝構(gòu)造有可能被優(yōu)化掉),拷貝的臨時變量銷毀調(diào)用一次析構(gòu),aa這個局部對象銷毀再調(diào)用一次析構(gòu),那這兩個析構(gòu)誰先調(diào)用的呢?拷貝構(gòu)造后面經(jīng)跟的就是拷貝時創(chuàng)建的臨時變量銷毀調(diào)用的析構(gòu)

此時還沒有優(yōu)化,但是當(dāng)我們來接受它的返回值時:

?

aa拷貝給一個臨時變量,臨時變量再拷貝給給aa1,這里就會被優(yōu)化為一個拷貝構(gòu)造。?

如果我們在將賦值重載再寫出來(下面的稱為賦值接受):

就會得到下面的結(jié)果:

?如果先定義一個對象,再接收返回值,就是aa2先構(gòu)造,func3里aa構(gòu)造,返回時一個拷貝構(gòu)造(這個拷貝構(gòu)造有可能會被優(yōu)化,因?yàn)闆]有創(chuàng)造新的對象來接收返回值,看編譯器,這里就是被優(yōu)化了)然后沒有被優(yōu)化,那會多出來一對拷貝構(gòu)造+析構(gòu)。結(jié)果中的兩個析構(gòu)分別是func3函數(shù)結(jié)束aa銷毀調(diào)用的析構(gòu)和main函數(shù)結(jié)束aa2銷毀的析構(gòu)。

如果是下面的場景(下面的稱為拷貝構(gòu)造接受):

如果直接調(diào)用fun2,返回的匿名對象調(diào)用一次構(gòu)造,匿名對象出了fun2析構(gòu)一次。

如果接收fun2的返回值,匿名對象A()先構(gòu)造一次,返回時拷貝構(gòu)造一次,返回給aa2再拷貝一次編譯器會優(yōu)化用 匿名對象直接構(gòu)造aa2,直接就是構(gòu)造一次,所以最后一次析構(gòu)是aa2銷毀的析構(gòu)

?

總結(jié):

優(yōu)化的場景很多,我們只要記住:

?

?

?

總結(jié):

若有歧義,請指出,感謝閱讀!

http://aloenet.com.cn/news/33120.html

相關(guān)文章:

  • ip動態(tài)地址做網(wǎng)站網(wǎng)站seo站長工具
  • 第一家做誘惑的網(wǎng)站廈門seo優(yōu)化
  • 貴州潤鐵祥建設(shè)工程有限公司網(wǎng)站外包公司軟件開發(fā)
  • 杭州江干區(qū)抖音seo哪里有五年級上冊語文優(yōu)化設(shè)計答案
  • 電子商務(wù)網(wǎng)站的作用seo排名第一的企業(yè)
  • win7iis部署asp.net網(wǎng)站媒體營銷平臺
  • 企業(yè)網(wǎng)站營銷優(yōu)缺點(diǎn)百度推廣平臺
  • 做網(wǎng)站費(fèi)用會計分錄百度貼吧網(wǎng)頁版登錄入口
  • 視頻網(wǎng)站 如何做seo專業(yè)seo公司
  • 什么網(wǎng)站可以做醫(yī)療設(shè)備的十大少兒編程教育品牌
  • 做家裝的設(shè)計公司網(wǎng)站seo廣告優(yōu)化
  • 網(wǎng)站模板更換營銷廣告語
  • 改版百度不收錄網(wǎng)站百度游戲中心app
  • 農(nóng)業(yè)信息免費(fèi)發(fā)布平臺合肥網(wǎng)站快速優(yōu)化排名
  • 怎樣用網(wǎng)站做淘寶推廣百度收錄教程
  • 成人用品網(wǎng)站怎么推廣推廣代理登錄頁面
  • 淮安市建設(shè)工程施工圖審查處網(wǎng)站微信營銷推廣公司
  • 免費(fèi)24小時咨詢醫(yī)生網(wǎng)站seo推廣計劃
  • 家政服務(wù) 技術(shù)支持 東莞網(wǎng)站建設(shè)真正的免費(fèi)建站在這里
  • b2c商城網(wǎng)站百度平臺電話
  • java做網(wǎng)站開發(fā)書seo綜合查詢 站長工具
  • 用凡科做網(wǎng)站的費(fèi)用百度競價推廣運(yùn)營
  • 數(shù)據(jù)庫支持的網(wǎng)站怎么做北京疫情最新情況
  • 金壇做網(wǎng)站鏈接交易網(wǎng)
  • 淘寶放單網(wǎng)站怎么做推客平臺
  • 如何做網(wǎng)站seo優(yōu)化惠州seo報價
  • 哪些網(wǎng)站可以做外部錨文本seo營銷推廣全程實(shí)例
  • 莆田 做網(wǎng)站的公司騰訊企點(diǎn)是干嘛的
  • 網(wǎng)站平臺搭建要多少錢seo發(fā)帖論壇
  • 東莞企業(yè)網(wǎng)站推廣哪里好網(wǎng)絡(luò)游戲推廣員的真實(shí)經(jīng)歷