您好,登錄后才能下訂單哦!
本篇內容主要講解“C++中默認操作怎么定義”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“C++中默認操作怎么定義”吧!
C.21:默認操作要定義就全定義,要禁止就全禁止
特殊的成員函數包括構造函數,拷貝構造函數,拷貝賦值運算符,移動構造函數,移動賦值運算符和析構函數。
譯者注:這些函數都具有管理數據成員生命周期的責任,因此實現還是禁止都需要統一。
特殊函數的語義緊密相關,如果一個需要聲明,可能其他的也需要考慮。
定義除默認構造函數之外的所有特殊函數,即使采用=default或者=delete的形式,將會抑制隱式聲明移動構造函數和移動賦值運算符。聲明移動構造函數或者移動賦值運算符,即使采用=default或者=delete的形式,也會導致隱式生成的拷貝構造函數或者拷貝賦值運算符被定義為=delete。因此,一旦任何一個特殊函數被聲明,其他的都應該被聲明以避免多余的效果。例如將所有的潛在移動操作都被變成代價高昂的拷貝操作,或者令這個類變成只移動的。
struct M2 { // bad: incomplete set of default operations
public:
// ...
// ... no copy or move operations ...
~M2() { delete[] rep; }
private:
pair<int, int>* rep; // zero-terminated set of pairs
};
void use()
{
M2 x;
M2 y;
// ...
x = y; // the default assignment
// ...
}
假設析構函數需要那個“特殊模式”(這里是釋放內存),那么(默認的,譯者注)拷貝和移動賦值(都會隱性銷毀對象)正確動作的可能性就會很低。
這就是眾所周知的"5特殊函數規則"或者"6特殊函數規則",不同之處在于是否將默認構造函數算進來。
Note(注意)
如果需要默認操作的默認實現(例如定義了其他非默認的),通過=default表示你是有意那么做的。如果不想要默認操作,通用=delete抑制它的產生。
譯者注:例如,如果定義了某種形式的構造函數,編譯器就不會生成默認的構造函數。
Example, good(示例)
如果需要聲明析構函數就直接定義為virtual,這個做法可以作為默認。為了避免抑制隱式的移動操作,它們也必須被聲明。為了避免類成為只移動(和拷貝禁止)類型,拷貝操作也必須聲明:
class AbstractBase {
public:
virtual ~AbstractBase() = default;
AbstractBase(const AbstractBase&) = default;
AbstractBase& operator=(const AbstractBase&) = default;
AbstractBase(AbstractBase&&) = default;
AbstractBase& operator=(AbstractBase&&) = default;
};
為了避免由于規則C.67產生的分歧,也可以將拷貝和移動運算符定義為刪除的。
class ClonableBase {
public:
virtual unique_ptr<ClonableBase> clone() const;
virtual ~ClonableBase() = default;
ClonableBase(const ClonableBase&) = delete;
ClonableBase& operator=(const ClonableBase&) = delete;
ClonableBase(ClonableBase&&) = delete;
ClonableBase& operator=(ClonableBase&&) = delete;
};
只定義移動操作或者拷貝操作產生的效果相同,但是應該明確地為每個特殊函數說明目的以便讓讀者更容易理解。
編譯器會強制執行本規則的大部分,理想情況會對任何違反發出警告。
Note(注意)
強烈反對一個具有析構函數的類依靠隱式產生的拷貝操作。
同時寫6個特殊成員函數容易發生錯誤。注意以下代碼中的參數類型。
class X {
public:
// ...
virtual ~X() = default; // destructor (virtual if X is meant to be a base class)
X(const X&) = default; // copy constructor
X& operator=(const X&) = default; // copy assignment
X(X&&) = default; // move constructor
X& operator=(X&&) = default; // move assignment
};
小錯誤(例如拼寫錯誤,落了const,用了&而不是&&,或者落了某個特殊成員函數)會引起錯誤或警告。為了避免無聊的代碼和可能的錯誤,努力踐行"0特殊函數"原則。
Enforcement(實施建議)
(簡單)類應該要么聲明(哪怕是通過=delete)所有的特殊函數,要么一個也不聲明。
到此,相信大家對“C++中默認操作怎么定義”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。