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

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í)所允許的情況難。

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)。
- 3 回答
- 0 關(guān)注
- 410 瀏覽
添加回答
舉報(bào)