<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          C++核心準(zhǔn)則C.21:默認(rèn)操作要定義就全定義,要禁止就全禁止

          cbec89377e5cd4359b4c7bfdb13325ba.webp

          C.21: If you define or =delete any default operation, define or =delete them all

          C.21:默認(rèn)操作要定義就全定義,要禁止就全禁止


          Reason(原因)

          The special member functions are the default constructor, copy constructor, copy assignment operator, move constructor, move assignment operator, and destructor.

          特殊的成員函數(shù)包括構(gòu)造函數(shù),拷貝構(gòu)造函數(shù),拷貝賦值運(yùn)算符,移動構(gòu)造函數(shù),移動賦值運(yùn)算符和析構(gòu)函數(shù)。

          譯者注:這些函數(shù)都具有管理數(shù)據(jù)成員生命周期的責(zé)任,因此實現(xiàn)還是禁止都需要統(tǒng)一。

          The semantics of the special functions are closely related, so if one needs to be declared, the odds are that others need consideration too.

          特殊函數(shù)的語義緊密相關(guān),如果一個需要聲明,可能其他的也需要考慮。

          Declaring any special member function except a default constructor, even as =default or =delete, will suppress the implicit declaration of a move constructor and move assignment operator. Declaring a move constructor or move assignment operator, even as=default or =delete, will cause an implicitly generated copy constructor or implicitly generated copy assignment operator to be defined as deleted. So as soon as any of the special functions is declared, the others should all be declared to avoid unwanted effects like turning all potential moves into more expensive copies, or making a class move-only.

          定義除默認(rèn)構(gòu)造函數(shù)之外的所有特殊函數(shù),即使采用=default或者=delete的形式,將會抑制隱式聲明移動構(gòu)造函數(shù)和移動賦值運(yùn)算符。聲明移動構(gòu)造函數(shù)或者移動賦值運(yùn)算符,即使采用=default或者=delete的形式,也會導(dǎo)致隱式生成的拷貝構(gòu)造函數(shù)或者拷貝賦值運(yùn)算符被定義為=delete。因此,一旦任何一個特殊函數(shù)被聲明,其他的都應(yīng)該被聲明以避免多余的效果。例如將所有的潛在移動操作都被變成代價高昂的拷貝操作,或者令這個類變成只移動的。

          譯者注:關(guān)于=default和=delete請參考以下鏈接:

          https://mp.weixin.qq.com/s/YgyRdwgkcKdbbmMAbU8Amg

          https://mp.weixin.qq.com/s/5yMBZWlKN_7OWhaJD4u_XQ


          Example, bad(反面示例)
          struct M2 {   // bad: incomplete set of default operations
          public:
          // ...
          // ... no copy or move operations ...
          ~M2() { delete[] rep; }
          private:
          pair* rep; // zero-terminated set of pairs
          };

          void use()
          {
          M2 x;
          M2 y;
          // ...
          x = y; // the default assignment
          // ...
          }

          Given that "special attention" was needed for the destructor (here, to deallocate), the likelihood that copy and move assignment (both will implicitly destroy an object) are correct is low (here, we would get double deletion).

          假設(shè)析構(gòu)函數(shù)需要那個“特殊模式”(這里是釋放內(nèi)存),那么(默認(rèn)的,譯者注)拷貝和移動賦值(都會隱性銷毀對象)正確動作的可能性就會很低。


          Note(注意)

          This is known as "the rule of five" or "the rule of six", depending on whether you count the default constructor.

          這就是眾所周知的"5特殊函數(shù)規(guī)則"或者"6特殊函數(shù)規(guī)則",不同之處在于是否將默認(rèn)構(gòu)造函數(shù)算進(jìn)來。


          Note(注意)

          If you want a default implementation of a default operation (while defining another), write =default to show you're doing so intentionally for that function. If you don't want a default operation, suppress it with =delete.

          如果需要默認(rèn)操作的默認(rèn)實現(xiàn)(例如定義了其他非默認(rèn)的),通過=default表示你是有意那么做的。如果不想要默認(rèn)操作,通用=delete抑制它的產(chǎn)生。

          譯者注:例如,如果定義了某種形式的構(gòu)造函數(shù),編譯器就不會生成默認(rèn)的構(gòu)造函數(shù)。


          Example, good(示例)

          When a destructor needs to be declared just to make it virtual, it can be defined as defaulted. To avoid suppressing the implicit move operations they must also be declared, and then to avoid the class becoming move-only (and not copyable) the copy operations must be declared:

          如果需要聲明析構(gòu)函數(shù)就直接定義為virtual,這個做法可以作為默認(rèn)。為了避免抑制隱式的移動操作,它們也必須被聲明。為了避免類成為只移動(和拷貝禁止)類型,拷貝操作也必須聲明:

          class AbstractBase {
          public:
          virtual ~AbstractBase() = default;
          AbstractBase(const AbstractBase&) = default;
          AbstractBase& operator=(const AbstractBase&) = default;
          AbstractBase(AbstractBase&&) = default;
          AbstractBase& operator=(AbstractBase&&) = default;
          };

          Alternatively to prevent slicing as per C.67, the copy and move operations can all be deleted:

          為了避免由于規(guī)則C.67產(chǎn)生的分歧,也可以將拷貝和移動運(yùn)算符定義為刪除的。

          class ClonableBase {
          public:
          virtual unique_ptr clone() const;
          virtual ~ClonableBase() = default;
          ClonableBase(const ClonableBase&) = delete;
          ClonableBase& operator=(const ClonableBase&) = delete;
          ClonableBase(ClonableBase&&) = delete;
          ClonableBase& operator=(ClonableBase&&) = delete;
          };

          Defining only the move operations or only the copy operations would have the same effect here, but stating the intent explicitly for each special member makes it more obvious to the reader.

          只定義移動操作或者拷貝操作產(chǎn)生的效果相同,但是應(yīng)該明確地為每個特殊函數(shù)說明目的以便讓讀者更容易理解。


          Note(注意)

          Compilers enforce much of this rule and ideally warn about any violation.

          編譯器會強(qiáng)制執(zhí)行本規(guī)則的大部分,理想情況會對任何違反發(fā)出警告。


          Note(注意)

          Relying on an implicitly generated copy operation in a class with a destructor is deprecated.

          強(qiáng)烈反對一個具有析構(gòu)函數(shù)的類依靠隱式產(chǎn)生的拷貝操作。


          Note(注意)

          Writing the six special member functions can be error prone. Note their argument types:

          同時寫6個特殊成員函數(shù)容易發(fā)生錯誤。注意以下代碼中的參數(shù)類型。

          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
          };

          A minor mistake (such as a misspelling, leaving out a const, using & instead of &&, or leaving out a special function) can lead to errors or warnings. To avoid the tedium and the possibility of errors, try to follow the rule of zero.

          小錯誤(例如拼寫錯誤,落了const,用了&而不是&&,或者落了某個特殊成員函數(shù))會引起錯誤或警告。為了避免無聊的代碼和可能的錯誤,努力踐行"0特殊函數(shù)"原則。


          Enforcement(實施建議)

          (Simple) A class should have a declaration (even a =delete one) for either all or none of the special functions.

          (簡單)類應(yīng)該要么聲明(哪怕是通過=delete)所有的特殊函數(shù),要么一個也不聲明。


          原文鏈接:

          https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c21-if-you-define-or-delete-any-default-operation-define-or-delete-them-all




          覺得本文有幫助?請分享給更多人。

          關(guān)注【面向?qū)ο笏伎肌枯p松學(xué)習(xí)每一天!

          面向?qū)ο箝_發(fā),面向?qū)ο笏伎迹?/span>



          瀏覽 34
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美三级欧美视频在线 | 天堂成人网站 | 一级A片逼 | 国产午夜成人电影 | 91高潮久久久久久久 |