Három szabály (C++)

Az oldal jelenlegi verzióját még nem ellenőrizték tapasztalt közreműködők, és jelentősen eltérhet a 2022. április 7-én felülvizsgált verziótól ; az ellenőrzések 2 szerkesztést igényelnek .

A három szabály (más néven "a három nagy törvénye" vagy "három nagy törvénye") egy C++ szabály , amely azt mondja, hogy ha egy osztály vagy struktúra definiálja a következő metódusok egyikét, akkor mindhárom metódust kifejezetten meg kell határoznia [1 ] :

Ez a három metódus speciális tagfüggvények , amelyeket a fordító automatikusan létrehoz, ha a programozó kifejezetten nem deklarálja. Ha az egyiket a programozónak kell definiálnia, akkor ez azt jelenti, hogy a fordító által generált verzió egy esetben nem elégíti ki az osztály igényeit, és valószínűleg más esetekben sem.

Ennek a szabálynak egy módosítása, hogy ha a RAII -t (az angolból.  Resource Acquisition Is Initialization ) használjuk, akkor a használt destruktor definiálatlan maradhat (néha a "Két nagy törvénye" néven is emlegetik) [2] .

Mivel az implicit módon definiált konstruktorok és hozzárendelési operátorok egyszerűen átmásolják egy osztály összes adattagját [3] , az explicit másoláskonstruktorok és másolás- hozzárendelési operátorok meghatározása szükséges olyan esetekben, amikor egy osztály összetett adatstruktúrákat foglal magában, vagy támogatja az erőforrásokhoz való kizárólagos hozzáférést. És olyan esetekben is, amikor az osztály állandó adatokat vagy hivatkozásokat tartalmaz.

Öt szabály

A tizenegyedik szabvány kiadásával a szabály kibővült, és az ötös szabályaként vált ismertté. Most a konstruktor implementálásakor végre kell hajtania:

Öt példa szabálya:

#include <cstring> osztályú RFive { privát : char * cstring ; nyilvános : // Konstruktor inicializálási listával és törzstel RFive ( const char * arg ) : cstring ( új karakter [ std :: strlen ( arg ) + 1 ]) { std :: strcpy ( cstring , arg ); } // Pusztító ~ RFive () { törölje [] cstring ; } // Konstruktor másolása RFive ( állandó RFive és egyéb ) { cstring = új karakter [ std :: strlen ( egyéb . cstring ) + 1 ]; std :: strcpy ( cstring , egyéb . cstring ); } // Konstruktor mozgatása, nokivéve - szabványos konténerek használatakor végzett optimalizálás érdekében RFive ( RFive és egyéb ) nem , kivéve { csstring = egyéb . csstring ; egyéb . cstring = nullptr ; } // A hozzárendelés operátorának másolása RFive & operátor = ( állandó RFive és egyéb ) { ha ( ez == és mások ) return * this ; char * tmp_cstring = new char [ std :: strlen ( egyéb . cstring ) + 1 ]; std :: strcpy ( tmp_cstring , egyéb . cstring ); törölje [] cstring ; cstring = tmp_cstring ; return * this ; } // Hozzárendelési operátor áthelyezése RFive & operátor = ( RFive && egyéb ) nem, kivéve { ha ( ez == és mások ) return * this ; törölje [] cstring ; csstring = egyéb . csstring ; egyéb . cstring = nullptr ; return * this ; } // Mindkét hozzárendelési utasítást lecserélheti a következő utasításra // RFive& operator=(RFive másik) // { // std::swap(csstring, other.cstring); // return *this; // } };

Idióma másolása és megosztása

Mindig kerülje ugyanazon kód megkettőzését, mert ha egy szakaszt módosít vagy javít, a többit is meg kell javítania. A másolás és csere idióma lehetővé teszi ennek elkerülését a  másolás konstruktor kódjának újrafelhasználásával, így az RFive osztályhoz létre kell hozni egy barátságos swap függvényt, és másolással és áthelyezéssel kell megvalósítani a hozzárendelés operátort. Sőt, ezzel a megvalósítással nem kell ellenőrizni az önkiosztást.

#include <cstring> osztályú RFive { // a kód többi része RFive & operator = ( const RFive & other ) // Hozzárendelés operátorának másolása { Rfive tmp ( egyéb ); csere ( * this , tmp ); return * this ; } RFive & operator = ( RFive && other ) // A hozzárendelés operátorának mozgatása { csere ( * ez , más ); return * this ; } barát érvénytelen csere ( RFive & l , RFive & r ) { std használatával :: swap ; csere ( l . cstring , r . cstring ); } // a kód többi része };

Az is célszerű, hogy a hozzárendelési operátorok a visszatérési értéket állandó hivatkozásként állítsák be: const RFive& operator=(const RFive& other);. Az extra const megakadályozza, hogy olyan obfuszkált kódot írjunk, mint ez: (a=b=c).foo();.

Nulla szabály

Martin Fernandez a nulla szabályt is javasolta. [5] E szabály értelmében nem szabad az öt függvény egyikét sem saját maga határoznia meg; létrehozásukat a fordítóra kell bízni (értéket rendelni hozzájuk = default;). Az erőforrások sajátításához egyszerű mutatók helyett speciális burkolóosztályokat kell használnia, például std::unique_ptrés std::shared_ptr. [6]

Linkek

  1. Bjarne Stroustrup . A C++ programozási nyelv  (neopr.) . - 3. - Addison-Wesley , 2000. - S. 283-284. - ISBN 978-0201700732 .
  2. Karlsson, Bjorn; Wilson, Matthew. A Kettő Nagy Törvénye . A C++ forrás . Artima (2004. október 1.). Hozzáférés dátuma: 2008. január 22. Az eredetiből archiválva : 2012. március 17.
  3. A C++ programozási nyelv  . - S. 271.
  4. Hozzárendelés operátor áthelyezése . En.CPPReference.com . Hozzáférés időpontja: 2014. december 22. Az eredetiből archiválva : 2014. december 23.
  5. Nulla szabály . Lángoló veszélyzóna . Letöltve: 2015. július 29. Az eredetiből archiválva : 2015. augusztus 29.
  6. Kulikov Sándor. Szabály 3, 5, 0 Habrahabr . Letöltve: 2016. február 14. Az eredetiből archiválva : 2016. február 22..