Kolmen sääntö (C++)

Kokeneet kirjoittajat eivät ole vielä tarkistaneet sivun nykyistä versiota, ja se voi poiketa merkittävästi 7. huhtikuuta 2022 tarkistetusta versiosta . tarkastukset vaativat 2 muokkausta .

Kolmen sääntö (tunnetaan myös nimellä "Kolmen suuren laki") on C++- sääntö , joka sanoo, että jos luokka tai rakenne määrittelee jonkin seuraavista menetelmistä, sen on määriteltävä eksplisiittisesti kaikki kolme menetelmää [1 ] :

Nämä kolme menetelmää ovat erityisiä jäsenfunktioita , jotka kääntäjä luo automaattisesti, ellei ohjelmoija ole erikseen ilmoittanut niitä. Jos jompikumpi niistä on ohjelmoijan määriteltävä, niin tämä tarkoittaa, että kääntäjän luoma versio ei yhdessä tapauksessa täytä luokan tarpeita, eikä välttämättä myöskään muissa tapauksissa.

Muutos tähän sääntöön on, että jos käytetään RAII :ta ( englanniksi.  Resource Acquisition Is Initialization ), käytetty tuhoaja voi jäädä määrittelemättömäksi (joskus kutsutaan "kahden suuren laiksi") [2] .

Koska implisiittisesti määritellyt konstruktorit ja osoitusoperaattorit yksinkertaisesti kopioivat kaikki luokan datajäsenet [ 3] , eksplisiittisten kopiointikonstruktoreiden ja kopiointiosoitusoperaattoreiden määrittäminen on tarpeen tapauksissa, joissa luokka kapseloi monimutkaisia ​​tietorakenteita tai voi tukea eksklusiivista pääsyä resursseihin. Ja myös tapauksissa, joissa luokka sisältää vakiodataa tai viittauksia.

Viiden sääntö

Yhdennentoista standardin julkaisun myötä sääntö laajeni ja tuli tunnetuksi viidennen sääntönä. Nyt, kun toteutat konstruktoria, sinun on toteutettava:

Viiden esimerkin sääntö:

#include <cstring> luokan RFive { yksityinen : char * cstring ; julkinen : // Konstruktori alustusluettelolla ja rungolla RFive ( const char * arg ) : cstring ( uusi merkki [ std :: strlen ( arg ) + 1 ]) { std :: strcpy ( cstring , arg ); } // Tuhoaja ~ RFive () { poista [] cstring ; } // Kopioi rakentaja RFive ( const RFive ja muut ) { cstring = uusi merkki [ std :: strlen ( muu . cstring ) + 1 ]; std :: strcpy ( cstring , muu . cstring ); } // Siirrä rakentaja, eipaitsi - optimointia varten käytettäessä vakiosäiliöitä RFive ( RFive & & muut ) ei paitsi { cstring = muu . cstring ; muu . cstring = nullptr ; } // Kopioi tehtävän operaattori RFive & operaattori = ( jatkuva RFive & muu ) { jos ( tämä == & muut ) palauta * tämä ; char * tmp_cstring = uusi merkki [ std :: strlen ( muu . cstring ) + 1 ]; std :: strcpy ( tmp_cstring , muu . cstring ); poista [] cstring ; cstring = tmp_cstring ; palauta * tämä ; } // Siirrä tehtävän operaattori RFive & operaattori = ( RFive && muu ) eipaitsi { jos ( tämä == & muut ) palauta * tämä ; poista [] cstring ; cstring = muu . cstring ; muu . cstring = nullptr ; palauta * tämä ; } // Voit myös korvata molemmat tehtävälausekkeet seuraavalla käskyllä // RFive& operator=(RFive muuta) // { // std::swap(csstring, other.csstring); // palauta *this; //} };

Kopioi ja jaa idiomi

Saman koodin kopioimista kannattaa aina välttää, sillä jos muutat tai korjaat yhden osion, sinun on muistettava korjata loput. Kopioi ja swap idiomi mahdollistaa tämän välttämisen  käyttämällä kopiointikonstruktorikoodia, joten RFive-luokassa joudut luomaan ystävällisen swap-toiminnon ja toteuttamaan osoitusoperaattorin kopioimalla ja liikkumalla sen läpi. Lisäksi tällä toteutuksella ei tarvitse tarkistaa itsemääräämistä.

#include <cstring> luokan RFive { // loput koodista RFive & operator = ( const RFive & other ) // Kopioi tehtävän operaattori { Rfive tmp ( muu ); swap ( * this , tmp ); palauta * tämä ; } RFive & operator = ( RFive && other ) // Siirrä tehtävän operaattori { swap ( * tämä , muu ); palauta * tämä ; } ystävän void swap ( RFive & l , RFive & r ) { käyttäen std :: swap ; swap ( l . cstring , r . cstring ); } // loput koodista };

Osoitusoperaattoreiden on myös tarkoituksenmukaista tehdä palautusarvosta vakioviite: const RFive& operator=(const RFive& other);. Ylimääräinen const estää meitä kirjoittamasta obfusoitua koodia, kuten tämä: (a=b=c).foo();.

Nollasääntö

Martin Fernandez ehdotti myös nollasääntöä. [5] Tämän säännön mukaan sinun ei pitäisi määritellä itse mitään viidestä funktiosta; on välttämätöntä uskoa niiden luominen kääntäjälle (määrittää niille arvo = default;). Omista resursseja yksinkertaisten osoittimien sijaan kannattaa käyttää erityisiä kääreluokkia, kuten std::unique_ptrja std::shared_ptr. [6]

Linkit

  1. Bjarne Stroustrup . C++-ohjelmointikieli  (uuspr.) . - 3. - Addison-Wesley , 2000. - S. 283-284. - ISBN 978-0201700732 .
  2. Karlsson, Björn; Wilson, Matthew. Kahden suuren laki . C++ lähde . Artima (1. lokakuuta 2004). Käyttöpäivä: 22. tammikuuta 2008. Arkistoitu alkuperäisestä 17. maaliskuuta 2012.
  3. ↑ C++ - ohjelmointikieli  . - S. 271.
  4. Siirrä tehtävän operaattori . En.CPPReference.com . Käyttöpäivä: 22. joulukuuta 2014. Arkistoitu alkuperäisestä 23. joulukuuta 2014.
  5. Nollasääntö . Flaming Dangerzone . Haettu 29. heinäkuuta 2015. Arkistoitu alkuperäisestä 29. elokuuta 2015.
  6. Kulikov Aleksanteri. Sääntö 3, 5, 0 Habrahabr . Haettu 14. helmikuuta 2016. Arkistoitu alkuperäisestä 22. helmikuuta 2016.