C++類(lèi)成員初始化的三種方式
前言:
在C++98中,支持了在類(lèi)聲明中使用等號(hào)“=”加初始值的方式,來(lái)初始化類(lèi)中靜態(tài)成員常量。這種聲明方式我們也稱(chēng)之為“就地”聲明。就地聲明在代碼編寫(xiě)時(shí)非常便利,不過(guò)C++98對(duì)類(lèi)中就地聲明的要求卻非常高。如果靜態(tài)成員不滿(mǎn)足常量性,則不可以就地聲明,而且即使常量的靜態(tài)成員也只能是整型或者枚舉型才能就地初始化。而非靜態(tài)成員變量的初始化則必須在構(gòu)造函數(shù)中進(jìn)行。
首先,先得了解一下C++支持哪幾種類(lèi)成員初始化的方式,你常用的又是哪一種。
一、初始化方式
1、初始化方式一:初始化列表
class A { public: int a; // 初始化列表 A(int a_):a(a_){} };
2、初始化方式二:構(gòu)造函數(shù)初始化
class A { public: int a; // 初始化列表 A(int a_, bool b) { a = a_; } };
3、初始化方式三:聲明時(shí)初始化(也稱(chēng)就地初始化,c++11后支持)
class A { public: int a = 1; // 聲明時(shí)初始化 A() {} };
在C++98中,支持了在類(lèi)聲明中使用等號(hào)“=”加初始值的方式,來(lái)初始化類(lèi)中靜態(tài)成員常量。這種聲明方式我們也稱(chēng)之為“就地”聲明。就地聲明在代碼編寫(xiě)時(shí)非常便利,不過(guò)C++98對(duì)類(lèi)中就地聲明的要求卻非常高。如果靜態(tài)成員不滿(mǎn)足常量性,則不可以就地聲明,而且即使常量的靜態(tài)成員也只能是整型或者枚舉型才能就地初始化。而非靜態(tài)成員變量的初始化則必須在構(gòu)造函數(shù)中進(jìn)行。比如,如下代碼在c++98中編譯
class Init { public: Init(): a(0) [] Init(int d): a(d) {} private: int a; const static int b = 0; int c = 1; // member, cannot pass build static int d = 0; // member, cannot pass build static const double e = 1.3; // not int or enum type, cannot pass build stati const char* const f = "e"; // not int or enum type, cannot pass build }
這非常不方便,所以在C++11中,標(biāo)準(zhǔn)允許非靜態(tài)成員變量的初始化有多種形式。具體而言,除了初始化列表外,在C++11中,標(biāo)準(zhǔn)還允許使用等號(hào)= 或者 花括號(hào){} 進(jìn)行就地的非靜態(tài)成員變量初始化。
struct init { int a = 1; double b {1.2}; };
大家知道,有幾種情況下推薦優(yōu)先使用列表初始化
- const成員變量只能用成員初始化列表來(lái)完成初始化,而不能在構(gòu)造函數(shù)內(nèi)賦值
- 初始化的數(shù)據(jù)成員是對(duì)象
- 需要初始化引用成員數(shù)據(jù)
具體的原因這里不細(xì)述,大家可以去看一下《C++ Primer》。
構(gòu)造函數(shù)初始化的本質(zhì)是賦值操作("="),這個(gè)方法存在兩個(gè)問(wèn)題,一個(gè)是比起初始化列表和就地初始化,此方式的效率偏低;第二個(gè)是可能存在錯(cuò)誤隱患。
先說(shuō)第一個(gè),賦值過(guò)程中會(huì)產(chǎn)生臨時(shí)對(duì)象,臨時(shí)對(duì)象的構(gòu)造析構(gòu)會(huì)造成效率損耗,初始化列表的方式就避免了產(chǎn)生臨時(shí)對(duì)象縮帶來(lái)的問(wèn)題。
第二個(gè)是,如果你沒(méi)有重寫(xiě)或者禁止賦值構(gòu)造函數(shù),c++會(huì)悄悄的加上默認(rèn)的賦值構(gòu)造函數(shù),這個(gè)時(shí)候也有可能帶來(lái)問(wèn)題。
從C++11之后,這三種初始化的方法都可以使用,并不會(huì)存在沖突,但是,他們之間是有優(yōu)先級(jí)順序的,這個(gè)優(yōu)先級(jí)來(lái)源于他們?cè)诔跏蓟臅r(shí)間順序,后面初始化的會(huì)把前面的覆蓋掉,成員變量的初始化順序是
二、聲明時(shí)初始化->初始化列表->構(gòu)造函數(shù)初始化
因此假如三種初始化方式同時(shí)存在的話(huà),那么最后保留的成員變量值肯定是構(gòu)造函數(shù)中初始化的值。
#include <iostream> using namespace std; class A { public: int a = 1; A(int a_) :a(2) { a = 3; } }; int main() { A a; cout << "a.a=" << a.a << endl; return 0; } // a.a=3
既然初始化方式這么多,那么什么時(shí)候適用哪種呢?
1、聲明時(shí)初始化的使用場(chǎng)景
一個(gè)優(yōu)點(diǎn)是直觀,你在聲明的時(shí)候順便給一個(gè)初始值,bravo
,別人在看你代碼的時(shí)候,點(diǎn)一下調(diào)到聲明也能看到你賦予的初始值,不用再去看構(gòu)造函數(shù)那里給的什么值
第二個(gè)優(yōu)點(diǎn)更有用了,比如你要定義多個(gè)構(gòu)造函數(shù),每個(gè)構(gòu)造函數(shù)都用列表初始化的方法初始化,多麻煩呀,請(qǐng)看下面的例子,媽媽看了再也不用擔(dān)心我想用其他初始化方法了
class Group { public: Group() {} Group(int a): data(a) {} Group(Mem m): mem(m) {} Group(int a, Mem m, string n): data(a), mem(m), name(n) {} private: int data = 1; Mem mem{0}; string name{"Group"}; };
2、列表初始化的使用場(chǎng)景
前面說(shuō)過(guò)了三個(gè)場(chǎng)景,這里贅述一下
const
成員變量只能用成員初始化列表來(lái)完成初始化,而不能在構(gòu)造函數(shù)內(nèi)賦值- 初始化的數(shù)據(jù)成員是對(duì)象
- 需要初始化引用成員數(shù)據(jù)
但是,需要注意列表初始化的順序,不過(guò)IDE會(huì)提示你的
3、構(gòu)造函數(shù)初始化的使用場(chǎng)景
第一個(gè)就是拷貝和賦值構(gòu)造函數(shù)里(不然怎么叫賦值構(gòu)造函數(shù)呢)
第二個(gè)就是比較無(wú)聊的情況了,比如你想把幾個(gè)成員函數(shù)都初始化成一個(gè)值,請(qǐng)看下面例子
class Group { public: Group() {data1 = data2 = data3 = 0;} private: int data1; int data2; int data3; };
一言以蔽之,優(yōu)先就地初始化和列表初始化。
到此這篇關(guān)于C++類(lèi)成員初始化的三種方式的文章就介紹到這了,更多相關(guān)C++類(lèi)成員初始化的方式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C/C++ winsock實(shí)現(xiàn)不同設(shè)備實(shí)時(shí)通訊的示例代碼
這篇文章主要為大家詳細(xì)介紹了C/C++如何利用winsock連接實(shí)現(xiàn)不同設(shè)備實(shí)時(shí)通訊,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-09-09C語(yǔ)言中do-while語(yǔ)句的2種寫(xiě)法示例
這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中do-while語(yǔ)句的2種寫(xiě)法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07C++實(shí)踐數(shù)組作數(shù)據(jù)成員的參考
今天小編就為大家分享一篇關(guān)于C++實(shí)踐數(shù)組作數(shù)據(jù)成員的參考,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-02-02