欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++聚合體初始化aggregate initialization詳細(xì)介紹

 更新時(shí)間:2023年02月03日 15:50:13   作者:另尋滄海  
這篇文章主要介紹了C++聚合體初始化aggregate initialization,C++有很多初始化對(duì)象的方法。其中之一叫做 聚合體初始化(aggregate initialization) ,這是聚合體專(zhuān)有的一種初始化方法

聚合體初始化(aggregate initialization)

C++有很多初始化對(duì)象的方法。其中之一叫做 聚合體初始化(aggregate initialization) ,這是聚合體專(zhuān)有的一種初始化方法。

從C語(yǔ)言引入的初始化方式是用花括號(hào)括起來(lái)的一組值來(lái)初始化類(lèi):

struct Data {
    std::string name;
    double value;
};
Data x = {"test1", 6.778};

自從C++11起,你可以忽略等號(hào):

Data x{<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->"test1", 6.778};

自從C++17起,聚合體可以擁有基類(lèi)。也就是說(shuō)像下面這種從其他類(lèi)派生出的子類(lèi)也可以使用這種初始化方法:

struct MoreData : Data {
    bool done;
}
MoreData y{{"test1", 6.778}, false};

如你所見(jiàn),聚合體初始化時(shí)可以用一個(gè)子聚合體初始化來(lái)初始化類(lèi)中來(lái)自基類(lèi)的成員。

另外,你甚至可以省略子聚合體初始化的花括號(hào):

MoreData y{<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->"test1", 6.778, false};

這樣寫(xiě)將遵循嵌套聚合體初始化時(shí)的通用規(guī)則,你傳遞的實(shí)參被用來(lái)初始化哪一個(gè)成員取決于它們的順序。

擴(kuò)展聚合體初始化的動(dòng)機(jī)

如果沒(méi)有這個(gè)特性,那么所有的派生類(lèi)都不能使用聚合體初始化,這意味著你要像下面這樣定義構(gòu)造函數(shù):

struct Cpp14Data : Data {
    bool done;
    Cpp14Data (const std::string& s, double d, bool b) : Data{s, d}, done {
    }
};
Cpp14Data y{"test1", 6.778, false};

現(xiàn)在我們不再需要定義任何構(gòu)造函數(shù)就可以做到這一點(diǎn)。

我們可以直接使用嵌套花括號(hào)的語(yǔ)法來(lái)實(shí)現(xiàn)初始化,

如果給出了內(nèi)層初始化需要的所有值就可以省略?xún)?nèi)層的花括號(hào):

MoreData x{{"test1", 6.778}, false};    // 自從C++17起OK
MoreData y{"test1", 6.778, false};      // OK

注意因?yàn)楝F(xiàn)在派生類(lèi)也可以是聚合體,所以其他的一些初始化方法也可以使用:

MoreData u;     // OOPS:value/done未初始化
MoreData z{};   // OK: value/done初始化為0/false

如果覺(jué)得這樣很危險(xiǎn),可以使用成員初始值:

struct Data {
    std::string name;
    double value{0.0};
};
struct Cpp14Data : Data {
    bool done{false};
};

或者,繼續(xù)提供一個(gè)默認(rèn)構(gòu)造函數(shù)。

使用聚合體擴(kuò)展

聚合體初始化的一個(gè)典型應(yīng)用場(chǎng)景是對(duì)一個(gè)派生自C風(fēng)格結(jié)構(gòu)體并且添加了新成員的類(lèi)進(jìn)行初始化。例如:

struct Data {
    const char* name;
    double value;
};
struct CppData : Data {
    bool critical;
    void print() const {
        std::cout << '[' << name << ',' << value << "]\n";
    }
};
CppData y{{"test1", 6.778}, false};
y.print();

這里,內(nèi)層花括號(hào)里的參數(shù)被傳遞給基類(lèi)Data。

注意你可以跳過(guò)初始化某些值。在這種情況下,跳過(guò)的成員將會(huì)進(jìn)行默認(rèn)初始化

(基礎(chǔ)類(lèi)型會(huì)被初始化為0false或者nullptr,類(lèi)類(lèi)型會(huì)默認(rèn)構(gòu)造)。

例如:

CppData x1{};           // 所有成員默認(rèn)初始化為0值
CppData x2{{"msg"}}     // 和{{"msg", 0.0}, false}等價(jià)
CppData x3{{}, true};   // 和{{nullptr, 0.0}, true}等價(jià)
CppData x4;             // 成員的值未定義

注意使用空花括號(hào)和不使用花括號(hào)完全不同:

x1的定義會(huì)把所有成員默認(rèn)初始化為0值,

因此字符指針name被初始化為nullptr,

double類(lèi)型的value初始化為0.0,

bool類(lèi)型的flag初始化為falsex4的定義沒(méi)有初始化任何成員。所有成員的值都是未定義的。

你也可以從非聚合體派生出聚合體。例如:

struct MyString : std::string {
    void print() const {
        if (empty()) {
            std::cout << "<undefined>\n";
        }
        else {
            std::cout << c_str() << '\n';
        }
    }
};
MyString x{{"hello"}};
MyString y{"world"};

注意這不是通常的具有多態(tài)性的public繼承,因?yàn)?code>std::string沒(méi)有虛成員函數(shù),

你需要避免混淆這兩種類(lèi)型。

你甚至可以從多個(gè)基類(lèi)和聚合體中派生出聚合體:

template<typename T>
struct D : std::string, std::complex<T>
{
    std::string data;
};

你可以像下面這樣使用和初始化:

D<float> s{{"hello"}, {4.5, 6.7}, "world"}; // 自從C++17起OK
D<float> t{"hello", {4.5, 6.7}, "world"};   // 自從C++17起OK
std::cout << s.data;                        // 輸出:"world"
std::cout << static_cast<std::string>(s);   // 輸出:"hello"
std::cout << static_cast<std::complex<float>>(s);   //輸出:(4.5,6.7)

內(nèi)部嵌套的初值列表將按照繼承時(shí)基類(lèi)聲明的順序傳遞給基類(lèi)。

這個(gè)新的特性也可以幫助我們用很少的代碼定義重載的lambda。

聚合體的定義

總的來(lái)說(shuō),在C++17中滿(mǎn)足如下條件之一的對(duì)象被認(rèn)為是 聚合體 :

  • 是一個(gè)數(shù)組
  • 或者是一個(gè)滿(mǎn)足如下條件的 類(lèi)類(lèi)型 (class、struct、union):
  • 沒(méi)有用戶(hù)定義的和explicit的構(gòu)造函數(shù)
  • 沒(méi)有使用using聲明繼承的構(gòu)造函數(shù)
  • 沒(méi)有privateprotected的非靜態(tài)數(shù)據(jù)成員
  • 沒(méi)有virtual函數(shù)
  • 沒(méi)有virtual, private, protected的基類(lèi)

然而,要想使用聚合體初始化來(lái) 初始化 聚合體,那么還需要滿(mǎn)足如下額外的約束:

  • 基類(lèi)中沒(méi)有private或者protected的成員
  • 沒(méi)有private或者protected的構(gòu)造函數(shù)

下一節(jié)就有一個(gè)因?yàn)椴粷M(mǎn)足這些額外約束導(dǎo)致編譯失敗的例子。

C++17引入了一個(gè)新的類(lèi)型特征is_aggregate<>

來(lái)測(cè)試一個(gè)類(lèi)型是否是聚合體:

template<typename T>
struct D : std::string, std::complex<T> {
    std::string data;
};
D<float> s{{"hello"}, {4.5, 6.7}, "world"};         // 自從C++17起OK
std::cout << std::is_aggregate<decltype(s)>::value; // 輸出1(true)

向后的不兼容性

注意下面的例子不能再通過(guò)編譯:

struct Derived;
struct Base {
    friend struct Derived;
private:
    Base() {
    }
};
struct Derived : Base {
};
int main()
{
    Derived d1{};   // 自從C++17起ERROR
    Derived d2;     // 仍然OK(但可能不會(huì)初始化)
}

在C++17之前,Derived不是聚合體。因此

Derived d1{};

會(huì)調(diào)用Derived隱式定義的默認(rèn)構(gòu)造函數(shù),這個(gè)構(gòu)造函數(shù)會(huì)調(diào)用基類(lèi)Base的構(gòu)造函數(shù)。

盡管基類(lèi)的默認(rèn)構(gòu)造函數(shù)是private的,但在派生類(lèi)的構(gòu)造函數(shù)里調(diào)用它也是有效的,

因?yàn)榕缮?lèi)被聲明為友元類(lèi)。

自從C++17起,例子中的Derived是一個(gè)聚合體,所以它沒(méi)有隱式的默認(rèn)構(gòu)造函數(shù)

(構(gòu)造函數(shù)沒(méi)有使用using聲明繼承)。因此,d1的初始化將是一個(gè)聚合體初始化,

如下表達(dá)式:

std::is_aggregate<Derived>::value

將返回true。

然而,因?yàn)榛?lèi)有一個(gè)private的構(gòu)造函數(shù)(見(jiàn)上一節(jié))所以不能使用花括號(hào)來(lái)初始化。

這和派生類(lèi)是否是基類(lèi)的友元無(wú)關(guān)。

到此這篇關(guān)于C++聚合體初始化aggregate initialization詳細(xì)介紹的文章就介紹到這了,更多相關(guān)C++聚合體初始化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++類(lèi)基本語(yǔ)法實(shí)例分析

    C++類(lèi)基本語(yǔ)法實(shí)例分析

    這篇文章主要介紹了C++類(lèi)基本語(yǔ)法實(shí)例分析,非常適合初學(xué)者學(xué)習(xí)借鑒,需要的朋友可以參考下
    2014-08-08
  • 溫故C語(yǔ)言?xún)?nèi)存管理

    溫故C語(yǔ)言?xún)?nèi)存管理

    這篇文章主要介紹了 C語(yǔ)言?xún)?nèi)存管理的相關(guān)資料,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-05-05
  • C語(yǔ)言 90后懷舊游戲超級(jí)瑪麗的實(shí)現(xiàn)流程

    C語(yǔ)言 90后懷舊游戲超級(jí)瑪麗的實(shí)現(xiàn)流程

    90后最風(fēng)靡的游戲是什么?第一個(gè)聯(lián)想到的肯定是插卡游戲機(jī)或者VCD加光盤(pán)運(yùn)行在電視機(jī)上的超級(jí)瑪麗了,它的經(jīng)典絕對(duì)可以排在第一位,長(zhǎng)大后的我們今天來(lái)用C語(yǔ)言重溫一下
    2021-11-11
  • C語(yǔ)言判斷字符串是否回文三種方法實(shí)例

    C語(yǔ)言判斷字符串是否回文三種方法實(shí)例

    回文就是字符串中心對(duì)稱(chēng),從左向右讀和從右向左讀的內(nèi)容是一樣的,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言判斷字符串是否回文的三種方法,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-03-03
  • C語(yǔ)言中while與do-while的介紹與注意事項(xiàng)

    C語(yǔ)言中while與do-while的介紹與注意事項(xiàng)

    對(duì)于C語(yǔ)言中的while與do-while,相信很多都再熟悉不過(guò)了,最近在工作中就用到了,所以想著總結(jié)一下,方便自己或者有需要的朋友們參考借鑒,文中通過(guò)示例代碼介紹的很詳細(xì),感興趣的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2016-10-10
  • C++實(shí)現(xiàn)第K順序統(tǒng)計(jì)量的求解方法

    C++實(shí)現(xiàn)第K順序統(tǒng)計(jì)量的求解方法

    這篇文章主要介紹了C++實(shí)現(xiàn)第K順序統(tǒng)計(jì)量的求解方法,很有借鑒價(jià)值的算法,需要的朋友可以參考下
    2014-08-08
  • C語(yǔ)言實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)

    C語(yǔ)言實(shí)現(xiàn)學(xué)生信息管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)學(xué)生信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • 基于typedef的用法詳解

    基于typedef的用法詳解

    本篇文章是對(duì)typedef的用法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • 深入解析C++中的字符數(shù)組和處理字符串的方法

    深入解析C++中的字符數(shù)組和處理字符串的方法

    這篇文章主要介紹了深入解析C++中的字符數(shù)組和處理字符串的方法,需要的朋友可以參考下
    2015-09-09
  • C語(yǔ)言堆結(jié)構(gòu)處理TopK問(wèn)題詳解

    C語(yǔ)言堆結(jié)構(gòu)處理TopK問(wèn)題詳解

    TopK問(wèn)題即在N個(gè)數(shù)中找出最大的前K個(gè),這篇文章將詳細(xì)講解如何利用小根堆的方法解決TopK問(wèn)題,文中代碼具有一定參考價(jià)值,快跟隨小編一起學(xué)習(xí)一下吧
    2022-06-06

最新評(píng)論