標籤:

關於 《C++ Primer 5th》,使用了「 =default 」的默認構造函數相關問題?

Primer 講默認構造函數和「=default」的小節,其曰:

"...Under the new standard, if we want the default behavior, we can ask the compiler to generate the constructor for us by writing =default after the parameter list. The =default can appear with the declaration inside the class body or on the definition outside the class body..."

在這個小節隨後提到:

「...if your compiler doesn"t support in-class initializers, your default constructor should use the constructor initializer list to initalize every member of the class」

我把這兩段話理解為:

1. 「=default」不僅能用於在類內部定義的默認構造函數,也能用於在類外部定義的默認構造函數

2. 用了「=default」的默認構造函數,還能用初始值列表指定默認初始化值,像這樣:

但實際在VS2016試了下,會報錯。

去Stack Overflow問了下,都告訴我用了「=default」的默認構造函數,就跟定義、初始值列表這些東西無緣了,有你沒我。

那麼是不是我理解的不對?如果我理解的正確:

1. 同時使用初始值列表和「=default」的默認構造函數,應該怎麼寫?

2. =default 究竟能不能用於默認構造函數的定義?該怎麼用?

以上,先謝過各位了。


這樣寫:

class Fuck
{
public:
string shit;
int bitch{};
int dung{};

Fuck()
:bitch(1) // 這個時候dung是0,跟你想要的功能一致。
{
}
};


should 理解成 「它是」,而不是 「你應該」。


先來翻譯一下:

在C++11新標準中,如果我們需要默認的行為,那麼可以通過在參數列表後面寫上=default來要求編譯器生成構造函數。其中,=default既可以和聲明一起出現在類的內部,也可以作為定義出現在類的外部。

如果你的編譯器不支持類內初始值,那麼你的默認構造函數就應該使用構造函數初始值列表類初始化類的每個成員。

定義Sales_data=default()這個構造函數的目的僅僅是因為我們既需要其他形式的構造函數,也需要默認的構造函數。

我的理解是:當你定義了其他的構造函數時,那麼編譯器就不會替我們生成合成的默認構造函數(Synthesized default constructor),如果你需要默認構造函數,就需要加上=default來「告訴」編譯器我們需要默認構造函數。

=default後,肯定和初始值列表無關了,因為只有沒有提供任何實參的構造函數才能被稱為默認構造函數,同理同時使用=default和初始化列表的默認構造函數也不存在,輪子哥那種應該是一種折中的方法吧。至於定義,我猜是這樣的:

class Sales_data{
public:
Sales_data() = default;
Sales_data(const std::string s) :bookNo(s){ }
private:
std::string bookNo;
};

//define Sales_data()
Sales_data::Sales_data()
{
bookNo = "default";
}


一個類裡面一定要有構造函數來初始化類裡面的每一個成員數據。如果人不寫就會由機器生成一個默認構造函數。相反的,如果人寫了構造函數,機器就不再默認生成默認函數。但是有時候人寫的構造函數並不初始化每一個成員數據,這時,因為人寫了構造函數,機器就不會再寫,於是就有一部分成員數據無法完成初始化。怎麼辦呢?加一個 =deflaut。這時沒人管的成員數據們就會進行默認初始化了。(解決你你問題的關鍵就是要知道:寫了=deflaut 之後,還可以繼續添加其他的構造函數來人為初始化成員數據,而不要誤以為可以直接用=deflaut 來人為初始化成員數據)

—————————————————————————求輪子哥點評@vczh


今天再看這個問題,突然明白了。

當時我疑惑的關鍵在於,把「默認構造函數」理解成了「由編譯器生成的構造函數」——其實只要是參數列表為空,就是「默認構造函數」,不管是「=default」,還是自己定義了初始值列表和函數體。

所以primer里那句「……默認構造函數能使用初始值列表……」就說得通了,和前面的「使用=default生成構造函數」並不矛盾。


如果你的編譯器不支持類內初始化,你應該用列表初始值來進行默認構造。

struct SalesData

{

SalesData()=defau<

/*這意味著數據成員執行類內初始化或者默認初始化

一般最好提供類內初始值,因為默認初始化時比較危險的(比如int型對象默認初始化是隨機值),或者有的類沒有默認構造,如果有該類的成員是無法被默認初始化的,這時候你就不能用=default了,而是用初始值列表來對他們進行初始化

如: SalesData():bookNo(""),revenue(0.0){}

總之書中的意思並不是說有了=default 還能再提供初始值列表了

*/

string bookNo;

double revenue = 0.0;//這個有的編譯器可能會不支持

};


=default是啥吧,就是你隨便寫了一個其他的好比有參數的構造函數,那麼不會再生成沒參數的構造函數了。

這個時候你還想要沒參數的default behavior的構造函數,又嫌全手寫麻煩,那麼一句=default 就OK了。

注意,是default behavior

你那個1的不是。


推薦閱讀:

內存池除了減少內存申請和釋放的開銷之外還有什麼提升性能或者方便之處?
為什麼c++不能把「= [] () ->」操作符重載為非成員函數?
為什麼這些年c語言統治了幾乎所有方面?
怎麼理解 `auto var = [&]() { /* things to do */ }`?
為什麼 C++ 列表初始化時會執行兩次拷貝構造函數?

TAG:C |