第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

C ++ 11允許非靜態(tài)和非const成員的類內(nèi)初始化。發(fā)生了什么變化?

C ++ 11允許非靜態(tài)和非const成員的類內(nèi)初始化。發(fā)生了什么變化?

C++
千萬(wàn)里不及你 2019-11-11 13:11:40
在C ++ 11之前,我們只能對(duì)整數(shù)或枚舉類型的靜態(tài)const成員執(zhí)行類內(nèi)初始化。Stroustrup在他的C ++ FAQ中對(duì)此進(jìn)行了討論,并給出了以下示例:class Y {  const int c3 = 7;           // error: not static  static int c4 = 7;          // error: not const  static const float c5 = 7;  // error: not integral};并進(jìn)行以下推理:那么為什么存在這些不便的限制呢?通常在頭文件中聲明類,并且通常將頭文件包含在許多翻譯單元中。但是,為避免復(fù)雜的鏈接器規(guī)則,C ++要求每個(gè)對(duì)象都有唯一的定義。如果C ++允許對(duì)需要作為對(duì)象存儲(chǔ)在內(nèi)存中的實(shí)體進(jìn)行類內(nèi)定義,則該規(guī)則將被打破。但是,C ++ 11放寬了這些限制,允許對(duì)非靜態(tài)成員進(jìn)行類內(nèi)初始化(第12.6.2 / 8節(jié)):在非委托構(gòu)造函數(shù)中,如果給定的非靜態(tài)數(shù)據(jù)成員或基類未由mem-initializer-id指定(包括沒有mem-initializer-list的情況,因?yàn)闃?gòu)造函數(shù)沒有ctor-initializer)并且該實(shí)體不是抽象類(10.4)的虛擬基類,則如果實(shí)體是具有brace-or-equal-initializer的非靜態(tài)數(shù)據(jù)成員,則按照8.5中的指定進(jìn)行初始化;否則,如果實(shí)體是變量成員(9.5),則不執(zhí)行初始化。否則,該實(shí)體為默認(rèn)初始化(8.5)。如果非常量成員用說(shuō)明constexpr符標(biāo)記,則9.4.2節(jié)還允許非常量成員的類內(nèi)初始化。那么,我們?cè)贑 ++ 03中受到限制的原因發(fā)生了什么?我們是否只是接受“復(fù)雜的鏈接器規(guī)則”,還是進(jìn)行了其他更改以使其更容易實(shí)現(xiàn)?
查看完整描述

3 回答

?
牛魔王的故事

TA貢獻(xiàn)1830條經(jīng)驗(yàn) 獲得超3個(gè)贊

簡(jiǎn)短的答案是,它們使鏈接程序保持相同,但代價(jià)是使編譯器比以前更加復(fù)雜。


即,除了導(dǎo)致鏈接器要定義多個(gè)定義之外,它仍然僅生成一個(gè)定義,而編譯器必須對(duì)其進(jìn)行分類。


這也導(dǎo)致程序員要整理出一些更復(fù)雜的規(guī)則,但是它非常簡(jiǎn)單,所以沒什么大不了的。當(dāng)您為單個(gè)成員指定了兩個(gè)不同的初始化程序時(shí),就會(huì)出現(xiàn)額外的規(guī)則:


class X { 

    int a = 1234;

public:

    X() = default;

    X(int z) : a(z) {}

};

現(xiàn)在,這時(shí)的額外規(guī)則處理a使用非默認(rèn)構(gòu)造函數(shù)時(shí)用于初始化的值。答案很簡(jiǎn)單:如果使用未指定任何其他值的構(gòu)造函數(shù),1234則將使用初始化a-但是,如果使用指定其他值的構(gòu)造函數(shù),1234則基本上忽略。


例如:


#include <iostream>


class X { 

    int a = 1234;

public:

    X() = default;

    X(int z) : a(z) {}


    friend std::ostream &operator<<(std::ostream &os, X const &x) { 

        return os << x.a;

    }

};


int main() { 

    X x;

    X y{5678};


    std::cout << x << "\n" << y;

    return 0;

}

結(jié)果:


1234

5678


查看完整回答
反對(duì) 回復(fù) 2019-11-11
?
交互式愛情

TA貢獻(xiàn)1712條經(jīng)驗(yàn) 獲得超3個(gè)贊

我猜想推理可能是在模板完成之前編寫的。對(duì)于C ++ 11支持模板的靜態(tài)成員而言,對(duì)于靜態(tài)成員的類內(nèi)初始化器來(lái)說(shuō),所有必需的“復(fù)雜鏈接器規(guī)則”已經(jīng)存在。


考慮


struct A { static int s = ::ComputeSomething(); }; // NOTE: This isn't even allowed,

                                                   // thanks @Kapil for pointing that out


// vs.


template <class T>

struct B { static int s; }


template <class T>

int B<T>::s = ::ComputeSomething();


// or


template <class T>

void Foo()

{

    static int s = ::ComputeSomething();

    s++;

    std::cout << s << "\n";

}

在所有三種情況下,編譯器的問題都是相同的:它應(yīng)在哪個(gè)轉(zhuǎn)換單元中發(fā)出的定義s以及對(duì)其進(jìn)行初始化所需的代碼?一種簡(jiǎn)單的解決方案是將其發(fā)送到任何地方,然后讓鏈接程序?qū)ζ溥M(jìn)行整理。這就是鏈接器已經(jīng)支持諸如之類的原因的原因__declspec(selectany)。沒有它,就不可能實(shí)現(xiàn)C ++ 03。這就是為什么沒有必要擴(kuò)展鏈接器的原因。


坦率地說(shuō):我認(rèn)為舊標(biāo)準(zhǔn)中的推理完全是錯(cuò)誤的。


更新


正如Kapil指出的那樣,當(dāng)前標(biāo)準(zhǔn)(C ++ 14)甚至不允許我的第一個(gè)示例。無(wú)論如何,我還是保留了它,因?yàn)镮MO是實(shí)現(xiàn)過程中最困難的情況(編譯器,鏈接器)。我的觀點(diǎn)是:即使是這種情況,也沒有比例如使用模板時(shí)所允許的情況難。


查看完整回答
反對(duì) 回復(fù) 2019-11-11
?
慕的地10843

TA貢獻(xiàn)1785條經(jīng)驗(yàn) 獲得超8個(gè)贊

從理論上講,So why do these inconvenient restrictions exist?...原因是有效的,但可以輕松地繞開它,而這正是C ++ 11所做的。


當(dāng)你有一個(gè)文件,它只是包括文件和忽略任何初始化。僅在實(shí)例化類時(shí)才初始化成員。


換句話說(shuō),初始化仍然與構(gòu)造函數(shù)聯(lián)系在一起,只是表示法有所不同并且更加方便。如果未調(diào)用構(gòu)造函數(shù),則不會(huì)初始化值。


如果調(diào)用了構(gòu)造函數(shù),則使用類內(nèi)初始化(如果存在)初始化值,否則構(gòu)造函數(shù)可以使用自己的初始化覆蓋它們。初始化的路徑本質(zhì)上是相同的,即通過構(gòu)造函數(shù)。


從Stroustrup自己在C ++ 11上的常見問題中可以明顯看出這一點(diǎn)。


查看完整回答
反對(duì) 回復(fù) 2019-11-11
  • 3 回答
  • 0 關(guān)注
  • 410 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)