[英]What's the point in defaulting functions in C++11?
默認構造函數將具有聲明,並且該聲明將受到正常訪問規則的約束。 例如,您可以使默認的復制構造函數受到保護。 如果沒有這些新聲明,默認生成的成員將是公共的。
來自Stroustrup網站的這些例子可能會幫助您理解這一點:
默認和刪除的功能 - 默認控制
現在可以直接表達“禁止復制”的常用習語:
class X { // ... X& operator=(const X&) = delete; // Disallow copying X(const X&) = delete; };
相反,我們也可以明確地說我們想要默認的復制行為:
class Y { // ... Y& operator=(const Y&) = default; // default copy semantics Y(const Y&) = default; };
明確關於默認值顯然是多余的,但是對這種效果的評論以及(更糟糕的)明確定義復制操作的用戶意味着給出默認行為並不罕見。 將它留給編譯器來實現默認行為更簡單,更不容易出錯,並且通常會導致更好的目標代碼。 “默認”機制可用於任何具有默認值的函數。 “刪除”機制可用於任何功能。 例如,我們可以消除不需要的轉換,如下所示:
struct Z { // ... Z(long long); // can initialize with an long long Z(long) = delete; // but not anything less };
除了更改生成函數的可訪問性(私有/受保護)之外,您還可以將它們設置為虛擬。
struct S
{
virtual ~S();
virtual S& operator=(const S&);
};
S::~S() = default;
S& S::operator=(const S&) = default;
可以修改默認函數的以下方面:
但要這樣做,必須在課外定義函數( C ++ 0x最終委員會草案中的8.4.2 / 2)。
勞倫斯·克勞爾的原始提案版本就在這里 。
感謝Roger Pate的澄清和引用。
1)隱式生成的析構函數目前不是虛擬的。 所以你需要定義它們以使它們成為虛擬的,在這種情況下它們不那么有效。 使用= default,您將同時擁有virtual和efficent作為隱式生成的析構函數。
2)它們將具有訪問說明符,與隱式生成的說明符相反。
3)如果你內聯你的默認構造函數,你的課程仍然是微不足道的。
參見Scott Meyer的偉大着作“ Effective Modern C ++ ”中的第17項。 它描述了生成(或生成)默認復制構造函數,復制操作和移動操作的許多條件。
換句話說,編譯器可能不“無論如何”。 但是,如果默認的特殊成員函數有意義,則用戶可以使用“default”關鍵字明確告訴編譯器生成一個默認函數,否則不會生成該函數。
從第17項末尾的事情開始:
僅為缺少顯式聲明的移動操作,復制操作或析構函數的類生成移動操作。
復制構造函數僅針對缺少顯式聲明的復制構造函數的類生成,如果聲明了移動操作,則會刪除它。 僅為缺少顯式聲明的復制賦值運算符的類生成復制賦值運算符,並且如果聲明了移動操作,則將其刪除。 不推薦使用顯式聲明的析構函數在類中生成復制操作。
我懷疑能夠默認生成復制構造函數實際上是有用的。 我無法看到默認生成默認構造函數的用法,因為正如您所說,您鍵入的實現將更短。
如果您有一個具有大量屬性的類,則默認對於復制構造函數更有用。 例如,如果您有這個類:
class MyClass {
private:
int offset;
std::string name;
std::vector<Person*> relatives;
float weight;
MyClass* spouse;
Vehicle* car;
double houseArea;
Date birth;
Person* parents[2];
public:
/* Default constructor will be defined here */
};
而不是這樣定義復制構造函數:
MyClass(const MyClass& that) :
offset(that.offset),
name(that.name),
relatives(that.relatives),
weight(that.weight),
spouse(that.spouse),
car(that.car),
houseArea(that.houseArea),
birth(that.birth),
parents(that.parents)
{}
你會這樣定義:
MyClass(const MyClass&) = default;
對我來說,它的禁用功能很有用,對於我目前創建的大多數類,我禁用復制和賦值 - 如果有一個編譯器可以識別的功能,而不是依賴於鏈接器錯誤,那將是很好的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.