offline
- Fil
- Legendarni građanin
- Pridružio: 11 Jun 2009
- Poruke: 16586
|
- 13Ovo se svidja korisnicima: TwinHeadedEagle, Srki_82, _Sale, mcrule, Mila_90, ivance95, Jimmy4, Brksi, NIx Car, DzoniB, vladasimovic, Gedza98, Srki94
Registruj se da bi pohvalio/la poruku!
[1] Klase
C++ provides the power; you supply the judgment
Programiranjem često rešavamo kompleksne probleme te je poželjno da se koriste i odgovarajuće reprezentacije objekata konkretnog problema.
Recimo, ukoliko treba da rešimo neki problem vezan za automobilsku industriju, barataćemo sa instancama (objektima) klase automobil, koje će imati odgovarajuće promenljive (recimo: brojBrzina, brojCilindara) i metode (recimo: Ubrzaj(), PromeniBrzinu() i druge).
Dakle, objekat predstavlja instancu neke klase. Klase predstavljaju korisnički definisane tipove.
Iz primera se vidi da promenljive čuvaju stanje nekog objekta, dok se metode odnose na ponašanje tog objekta. U ovom smislu, objekat predstavlja kolekciju određenih stanja i ponašanja.
* Napomena: više o klasama je pisano u člancima za C#, tako da preporučujem čitanje tih članaka. Koncept je isti, a sintaksa skoro pa jednaka.
Deklaracija klase:
class Automobil
{
unsigned int brojBrzina;
unsigned int brojCilindara;
void Ubrzaj();
};
Napomena: uočimo karakter ";" na kraju deklaracije klase! U programskim jezicima Java i C# nema karaktera ";" kod deklaracije klasa!
Deklaracije klase ne alocira (rezerviše) memoriju za klasu Automobil.
--> deklaracija služi da kompajler "obavestimo" šta predstavlja klasa Automobil, dakle, kakve podatke sadrži i šta može da radi.
--> Na osnovu ovoga kompajler zna koliko memorijskog prostora treba da "ostavi sa strane" objekte klase Automobil.
Pošto int zauzima 4 bajta, a imamo dve promenljive u klasi, --> objekat ove klase će biti "težak" 8 bajtova. Metode se ne uzimaju u obzir kod utvrđivanja veličine u memoriji.
Prilikom kreiranja koda programa treba, dakle, obratiti pažnju sa kakvim promenljivim, tj. sa kakvim tipovima promenljivih baratamo. Tip promenljive ukazuje na:
a) veličinu promenljive u memoriji,
b) kakvu vrstu podatka promenljiva može da čuva,
c) kakve akcije se mogu izvršiti nad promenljivima.
Dalje, treba obratiti pažnju i na stil programiranja. Ukoliko se držite jednog stila programiranja (davanja imena promenljivima, metodama i sl. ) lakše ćete protumačiti kod. Firme obično propisuju ova stilska pravila (standardni kodeks).
Definisanje objekta:
Automobil lada;
Ovim se definiše objekat klase (tj. tipa) Automobil. Ovo je korak u kome se rezerviše memorija za objekat.
Kako su sve članice klase privatne (ako se ne naznači drugačije), na sledeći način je moguće javno pristupiti članicama klase:
class Automobil
{
public:
unsigned int brojBrzina;
unsigned int brojCilindara;
void Ubrzaj();
};
* Opet vidimo razliku u sintaksi sa, recimo, srodnim jezicima Javom i C# ; kod njih se ispred svake promenljive definiše modifikator pristupa (dakle, public int brojBrzina;
public int brojCilindara; )
Bitno je reći da će public biti sve članice:
a) do navoda ključne reči private
b) do kraja deklaracije klase
Primer:
U primeru se vidi generalno pravilo dobrog dizajna - članice klase treba da su privatne. Pošto su promenljive privatne, moramo imati neke metode koje će služiti za manipulaciju nad tim podacima (čitanje i izmena vrednosti promenljivih). Te metode se nazivaju Accessor metode. Na ovaj način se omogućava odvajanje detalja implementacije i upotrebe (tj. manipulacije).
Accessor metode su tzv. Setteri i Getteri, koje su public metode i služe za promenu vrednosti, odnosno čitanje vrednosti promenljivih.
Citat Stroustrup-a: "The C++ access control mechanisms provide protection against accident—not against fraud."
Objekat pristupa public članicama klase vrši sa operatorom "."
Obratiti pažnju i na označavanje da metoda (implementirana izvan klase) pripada nekoj klasi, tj. ": :"
Konstrukor služi za instanciranje/inicijalizaciju objekta neke klase. Konstruktor, tehnički gledano, predstavlja posebnu metodu:
- koja ima naziv isto kao i naziv konkretne klase
- koja ne vraća povratnu vrednost
C++, za razliku od C# i Jave, nema garbage collection (koji se brine o "čišćenju" objekata), te prilikom deklarisanja konstruktora, treba deklarisati i odgovarajući destruktor. Destruktor se formira na sledeći način: "~"+naziv konstruktora. Dakle, ako je konstruktor: Automobil(), destruktor će biti ~Automobil().
dok konstruktori mogu imati ulazne argumente, destruktori ne primaju argumente.
Jedna klasa može imati više konstruktora (sa različitim parametrima).
Ukoliko ne deklarišemo konstruktor/desktruktor, generiše se podrazumevani konstruktor/destruktor.
Default constructor/destructor nema argumenata i ne radi ništa!
(primetimo da u prošlom primeru nije eksplicitno naveden konstruktor, te u tom slučaju, kako smo rekli, kompajler obezbeđuje default konstruktor. Zbog toga prethodni kod nije generisao grešku )
U sledećem primeru, biće upotrebljen non default konsruktor (prethodni primer će biti za nijansu proširen):
[2] Pokazivači
Pokazivač ili pointer je promenljiva koja čuva memorijsku adresu.
Pogledajmo sledeću sliku:
Na slici je prikazano:
- vrlo prosta šema memorije na računaru. Dakle, memorija računara je podeljena na sekvencijalno označene memorijske lokacije, zvane adrese.
Svaka promenljiva se nalazi na unikatnoj lokaciji u memoriji, tj. na određenoj adresi.
- pointer a koji pokazuje na promenljivu b.
* promenljiva b se nalazi na memorijskoj lokaciji 1462 i čuva vrednost 17
* pokazivač a se nalazi na memorijskoj lokaciji 874 i čuva memorijsku adresu promenljive b, dakle: 1462
pomoću adresnog operatora & može se videti memorijska adresa neke promenljive, Vidimo sledeći primer:
Oznake memorijske lokacije zavise od operativnog sistema i konkretnog kompajlera.
// U primerima šeme memorije, obično adresu apstrahujemo sa brojčanom vrednošću.
Podsetimo se, od tipa promenljive zavisi koliko će biti rezervisano i dodeljeno memorijskog prostora. Pogledajmo još jednu šemu:
Pointer "nekiPointer", koji treba da čuva adresu neke promenljive tipa int, ćemo deklarisati na sledeći način:
int *nekiPointer = NULL;
Dakle, na ovaj način je nekiPointer deklarisan da čuva adresu promenljive koja može biti tipa int.
Što se tiče dalje manipulacije sa pointerima, ponašaju se isto kao i svaka druga promenljiva.
Razlika između promenljive tipa int i pointera koji pokazuje na neki int je ta što promenljiva tipa int čuva integer, a pointer čuva adresu.
Neka vam bude obavezna praksa da inicijalizujete pointere !
- ukoliko se pointer inicijalizuje sa konstantom NULL - zove se Null Pointer
- pointer koji nij inicijalizovan se zove divlji pointer (wild pointer) i ovo treba strogo izbegavati.
Pridruživanje adrese pointeru:
unsigned short int nekiInt = 45;
unsigned short int * nekiPointer = NULL;
nekiPointer = &nekiInt;
Pristup nekoj promenljivoj preko njenog pokazivača naziva se indirekcija.
Mnoge firme koriste konvenciju davanja imena pointera, tako što ime pointera počinje sa malim "p". Na primer: pGodina.
Operator "*" se naziva indirection operator, ili dereference operator.
Ukoliko treba nekoj promenljivoj da dodelimo vrednost na čiju adresu gađa pointer, to ćemo učiniti ovako:
unsigned short int primer;
primer = *nekiPointer;
Dakle, opet se koristi indirection operator (*) i označava "vrednost na ovoj adresi."
// dakle uzimamo vrednost sa adrese koju čuva nekiPointer i dodeljujemo promenljivoj "primer".
Kao što se može videti, operator " * " ima dvojaku ulogu:
- deklaracija pointera
- ukazivanje na samu vrednost, ne na memorijsku adresu
// Mala digresija: " * " predstavlja i operator množenja, ali kompajler zna "da odabere" pravu funkciju operatora, na osnovu konteksta.
Pokazivači se najčešće koriste za tri zadatka:
- upravljanje podataka na heap-u (free store)
- pristup članicama klase
- prenos promenljivih po referenci
Naime, postoje sledeća polja memorije:
Citat:The stack
Code space
Global name space
Registers
The free store (heap)
- na stack-u se skladište lokalne promenljive i parametri funkcija
* kada funkcija vrati neku vrednost, lokalne promenljive se odbacuju
* stack se automatski čisti, kada funkcija vrati vrednost (samim tim i promenljive gube svoj opseg (scope))
- u Code space-u se skladišti kod.
- globalne promenljive se skladište na global name space-u.
- registers se koriste za interne funkcije održavanja (npr. stanje na vrhu stack-a i pokazivač za instrukcije)
- skoro sav preostali deo memorije predstavlja free store, odnosno heap.
Objekti na heap-u su trajni (perzistentni) i "ostaju" i posle return-a funkcije (za razliku od stack-a, gde ovo nije slučaj ! )
* alokacija memorije na heap se vrši sa ključnom reči "new":
unsigned short int * pPointer;
pPointer = new unsigned short int;
*pPointer = 72;
// new vraća memorijsku adresu
// *pPointer = 72; --> stavi vrednost 72 na lokaciju gde pointer pokazuje
* ne zaboravi da obrišeš pointer: ključna reč delete.
Dakle, kada se završi rad sa nekom memoijskom lokacijom, potrebno je da se pobriše pointer. Upotrebom ključne reči delete, oslobađa se memorija na heap-u i deklariše kao raspoloživa.
* delete se mora koristiti inače će se javiti memory leak
--> fora je u tome da pointer predstavlja lokalnu promenljivu, i kao takav nestaje kada funkcija vrati vrednost (tj. kada izgubi scope). Međutim, memorija na koju pointer pokazuje nije lokalnog karaktera i ne oslobađa se automatski.
Dakle, ukoliko se izgubi pokazivač na tu lokaciju, ona će ostati rezervisana (ukoliko se ne oslobodi sa delete), jer ne postoji neki drugi način da se otkrije koja memorijska lokacija se treba osloboditi (i opet staviti na raspolaganje).
Ova situacija se zove memory leak jer se ovako zauzeta memorije ne može povratiti sve dok se program ne završi (u toku rada programa, memorija kao da je "iscurela".)
uvek treba koristiti ključnu reč delete
Citat:delete pPointer;
// oslobodi memorijsku lokaciju na adresi na koju pointer pokazuje.
treba napomenuti da se ovim ne briše pointer! Znači, pointeru je i dalje "u opticaju" i može mu se dodeliti neka druga adresa.
Animal *pDog = new Animal; //alocates the memory
delete pDog; //frees the memory
pDog = NULL; //sets pointer to null
//...
delete pDog; //legit
Primer:
Demonstracija pointera i ključne reči delete
+ Vidi kod#include<iostream>
using namespace std;
int main (int argc, char *argv[]) {
int localVariable = 5; // declaracija i inicijalizacija lokalne promenljive
int * pLocal= &localVariable; //deklaracija i inicijalizacija pointera adresom lokalne promenljive
int * pHeap = new int; // deklariše drugi pointer i inicijalizuje ga sa adresom novog int-a (new int)
*pHeap = 7;
cout << "localVariable: " << localVariable << "\n";
cout << "*pLocal: " << *pLocal << "\n";
cout << "*pHeap: " << *pHeap << "\n";
delete pHeap;
pHeap = new int;
*pHeap = 9;
cout << "*pHeap: " << *pHeap << "\n";
delete pHeap;
return 0;
}
Ovo je primer bez mehanizama provere na grešku. Jedan od mehanizama "defanzivnog programiranja" je da testiramo da li je pointer null pre inicijalizacije.
Primer memory leak-a:
(dodela druge adrese pointeru bez prethodnog brisanja memorije na koju pokazuje)
Citat:unsigned short int *pPointer =new unsigned short int; //rezervise se memorija
*pPointer =72; //upisuje se vrednost u memoriju
pPointer =new unsigned short int; //rezervise se drugi memorijski prostor (prethodni nije oslobodjen)
*pPointer =84; //upisuje se vrednost u "drugi" memorijski prostor
* Ne postoji način da se oslobodi prva memorija, budući da nema pokazivača, te se više ne zna lokacija tog prostora. Oslobodiće se tek po završetku programa.
* Pre linije: "pPointer =new unsigned short int;", treba staviti: "delete pPointer;" da ne bi bilo curenja memorije.
Svaki put kada se koristi ključna reč "new" u programu, takođe treba biti i odgovarajući delete, kako bi memorija opet bila dostupna za upis na heap-u.
Primer: eksplicitno brisanje sa heap-a i implicitno brisanje sa stack-a
+ Vidi kompletan kod#include<iostream>
using namespace std;
//klasa
class Malware
{
public:
Malware();
~Malware();
private:
int itsNumber;
};
//konstruktor & destruktor
Malware::Malware()
{
cout << "Nadjen malware.\n ";
itsNumber =1;
}
Malware::~Malware()
{
cout << "Malware obrisan.\n ";
}
//main metoda
int main (int argc, char *argv[]) {
cout << "Malware Virut...\n ";
Malware Virut; //Malware Virut je kreiran na Stack-u
cout << "Linija: Malware *pKido = new Malware...\n";
Malware *pKido = new Malware; //kido pokazuje na Malware na Heap-u
cout << "Linija: delete pKido...\n";
delete pKido; //eksplicitno brisanje Kido-a.
cout << "Izlazim, Virut treba da bude pobrisan...\n";
return 0; //ovim se brise Malware sa Stack-a jer je van opsega!
}
* pristup clanicama preko pointera, primer: (*pKido).GetNumber();
* ili preko "point to operator" tj. "->", primer: pKido->GetNumber();
// i ovo je "indirection operator"
Primer upotrebe operatora:
+ Vidi kompletan kod#include<iostream>
using namespace std;
class Malware
{
public:
Malware();
~Malware();
int GetDetected() const {return *itsDetected;}
void SetDetected(int number) { *itsDetected = number; }
int GetRemoved() const {return *itsRemoved;}
void setRemoved (int number){*itsRemoved = number;}
private:
int *itsDetected;
int *itsRemoved;
};
Malware::Malware()
{
itsDetected = new int(10);
itsRemoved = new int(6);
}
Malware::~Malware()
{
delete itsDetected;
delete itsRemoved;
}
int main (int argc, char *argv[]) {
Malware *Virut =new Malware;
cout << "Pre skeniranja, na racunaru ima " << Virut->GetDetected() << " Virut detekcija\n";
Virut->SetDetected((Virut->GetDetected())-(Virut->GetRemoved()));
cout << "Posle skeniranja, racunaru ima " << Virut->GetDetected() << " Virut detekcija\n ";
delete Virut;
return 0;
}
* dve varijable članice su pointeri ka integerima
* konstruktor inicijalizuje pointere da pokazuju na vrednost u memoriji (heap)
* destruktor briše alociranu memoriju
* main funkcija nema pojma da su itsDetected i itsRemoved pointeri koji pokazuju na neku lokaciju na heap-u. Oslobođena je znanja o memorijskoj lokaciji, jer zna samo za GetDetected() i SetDetected(). Dakle, svi detalji o implenetaciju su sakriveni unutar klase (baš kako i treba da bude).
* Posmatrajmo liniju "delete Virut;"
Kada se Virut obriše na liniji 40, poziva se njegov destruktor (~Malware) i on briše promenljive članice klase (koji su pointeri !) . E sad, kako oni pokazuju na Integere, njihovi implicitni destruktori će biti pozvani.
ključna reč this predstavlja pointer ka tekućem objektu. Svaka metoda klase ima ovaj "skriveni parametar". Primer upotrebe:
Citat: public:
Rectangle();
~Rectangle();
void SetLength(int length) { this->itsLength =length;}
int GetLength() const { return this->itsLength; }
+ Vidi kompletan kod#include<iostream>
using namespace std;
class Rectangle
{
public:
Rectangle();
~Rectangle();
//sa this
void SetLength(int length) { this->itsLength=length;}
int GetLength()const { return this->itsLength; }
//bez this
void SetWidth(int width) { itsWidth=width; }
int GetWidth()const { return itsWidth; }
private:
int itsLength;
int itsWidth;
};
//konstruktor & destruktor
Rectangle::Rectangle() { itsWidth=2; itsLength=3; }
Rectangle::~Rectangle(){ }
int main (int argc, char *argv[]) {
Rectangle theRect;
cout << "theRect is " << theRect.GetLength() << " cm long.\n ";
cout << "theRect is " << theRect.GetWidth() << " cm wide.\n ";
theRect.SetLength(20);
theRect.SetWidth(10);
cout << "theRect is " << theRect.GetLength() << " cm long.\n ";
cout << "theRect is " << theRect.GetWidth() << " cm wide.\n ";
return 0;
}
* Napomena: this pointeri se ne brišu eksplicitno! O ovome ne moramo da brinemo jer se o tome brine kompajler.
Pored memory leak-a, još jedna bitna stvar kod pointera, a na koju treba da obratimo pažnju, su takozvani: dangling, stray ili wild pointeri (divlji ili zalutali pokazivači). O čemu se ovde radi?
--> divlji pokazivač se kreira kada pozovemo delete nekog pokazivača pokazivača (i samim tim oslobodimo memoriju na koju pokazuje), ali ga ne postavimo na NULL nakon oslobađanja memorije!
Budući da je oslobođena memorija dostupna za neki drugi upis, ukoliko ne NULL-ujemo pokazivač, on će pokazivati na istu memorijsku lokaciju, u kojoj se sada nalazi neki drugi sadržaj
Ukoliko se u programu i dalje koristi daj pointer, rezultat tog programa je tada vrlo nepredvidiv!
(ilustrativan primer je, da imamo memorisan broj neke kompanije na telefonu. Kompanija se može ugasiti ili preseliti i taj broj postaje dostupan za neku drugu firmu. Dakle, ako pozovemo taj memorisani broj (koji je u međuvremenu dodeljen nekoj drugoj firmi), dobićemo uslovno rečeno - nepredviđen rezultat (umesto da se završi posao sa prvobitnom firmom, komunicira se sa drugom firomom i prekida se poziv, pri čemu posao nije obavljen)).
Naravoučenije - uvek kada pozovemo delete pointera, postavimo taj pointer da pokazuje na NULL ili nullptr.
// Više o tome - u ovoj temi: http://www.mycity.rs/C/Analiza-situacije-Stomping-on-a-C-pointer.html
Još jedan primer rada sa pokazivačima, koji će biti jasniji kroz iteracije u debugger-u:
+ KOD#include <iostream>
#include <ctype.h>
#include <string.h>
//deklaracija/definicija
bool GetWord(char* theString, char* word, int& wordOffset);
int main()
{
const int bufferSize = 255;
char buffer[bufferSize+1]; // hold the entire string
char word[bufferSize+1]; // hold the word
int wordOffset = 0; // start at the beginning
std::cout << "Unesite recenicu: ";
std::cin.getline(buffer,bufferSize); //getline method
while (GetWord(buffer,word,wordOffset))
{
std::cout << "Nasao sam ovu rec: " << word << std::endl;
}
return 0;
}
// implementacija
bool GetWord(char* theString, char* word, int& wordOffset)
{
if (!theString[wordOffset]) // end of string?
return false;
char *p1, *p2;
p1 = p2 = theString+wordOffset; // point to the next word
// eat leading spaces
for (int i = 0; i<(int)strlen(p1) && !isalnum(p1[0]); i++)
p1++;
// see if you have a word
if (!isalnum(p1[0]))
return false;
// p1 now points to start of next word
// point p2 there as well
p2 = p1;
// march p2 to end of word
while (isalnum(p2[0]))
p2++;
// p2 is now at end of word
// p1 is at beginning of word
// length of word is the difference
int len = int (p2 - p1);
// copy the word into the buffer
strncpy (word,p1,len);
// null terminate it
word[len]='\0';
// now find the beginning of the next word
for (int j = int(p2-theString); j<(int)strlen(theString)
&& !isalnum(p2[0]); j++)
{
p2++;
}
wordOffset = int(p2-theString);
return true;
}
[3] Reference
Referencu možemo shvatiti kao sinonim, alternativno ime za objekat, gde se svaka manipulacija sa objektom - direktno odnosi na "imenovani" objekat.
Za kreiranje reference se koristi reference operator - &.
int &rNekaReferenca = 55;
Napomena: & predstavlja i:
- reference operator
- i address operator.
// Nisu isti operatori u pitanju (iako je oznaka ista) i kompajler zna na sta se tačno odnosi koji operator.
Primer:
+ KOD#include <iostream>
using namespace std;
int main()
{
int intOne;
int &rSomeRef = intOne;
intOne = 5;
cout << "intOne: " << intOne << endl; //5
cout << "rSomeRef: " << rSomeRef << endl; //5
rSomeRef = 7; //ovom prilikom se menja zapravo intOne, buduci da je refernca samo "alias"
cout << "intOne: " << intOne << endl; // 7
cout << "rSomeRef: " << rSomeRef << endl; //7
return 0;
}
Reference moraju biti inicijalizovane (za vreme kreacije)
Reference treba koristiti jer se sa njma postiže veća efikasnost programa.
- Svaki put kada se funkciji prosledi objekat po vrednosti --> pravi se kopija tog objekta.
- Svaki put kada se vrati objekat iz funkcije (return) po vrednosti --> opet se pravi kopija nekog objekta.
Ovi objekti se ne kopiraju na heap, već na stack (dakle, ako prenosimo po vrednosti) i na taj način imamo utrošak i vremena i memorije.
Prenos objekta po vrednosti je pogodan za manje objekte (tipa int), ali za veće objekte, korisnički definisane ovaj oblik nije pogodan, stoga se prenos treba vršiti po referenci. U jednom od narednih članaka će biti opisan prenos po referenci i napredne manipulacije sa funkcijama.
Refernce VS pokazivači
- pokazivači, ukoliko nisu inicijalizovani ili kada se brišu, treba da budu NULL (nullptr).
- referenca ne može biti NULL (ako se desi da referenca bude null, doći će do greške ili nepredviđenih situacija).
- reference se lakše koriste i većina C++ programera preferiraju refernce, umesto pokazivača. Savet je da se pokazivači ne koriste ukoliko reference mogu da "završe posao".
- Pointeri nude veću fleksibilnost, ali su komplikovaniji za upotrebu. Sa njima treba postupati vrlo oprezno.
- Reference bolje sakrivaju detalje u kodu, što će se videti u kasnijim primerima serijala (em nema potrebe za neprestanim dereferenciranjem promenljive, em je indirekcija skrivena).
- Dok se pokazivači mogu pokazivati na jedan objekat, a potom na drugi
- reference se vezuju samo za jedan objekat (svaka manipulacija nad referencom se odnosi baš za taj konkretni objekat, + adresa reference predstavlja memorijsku adresu posmatranog objekta kome je refernca alias) .
Trivia/Napomene
* Sve članice klase su podrazumevano privatne. Dakle, može im se pristupiti jedino na nivou metoda same klase.
* Inicijalizacija predstavlja deklaraciju promenljive uz dodelu vrednosti (npr. int i = 5
* Ako napišemo sopstveni konstruktor, kompajler neće da obezbedi default konstruktor! Dakle, ako naš konstruktor prima neki parametar, kompajler neće obezbediti default konstruktor. Ukoliko želimo konstruktor bez parametara, moraćemo ga sami programirati.
* Reference moraju biti inicijalizovane! Ukoliko deklarišemo referencu, a ne inicijalizujemo je, dobićemo compile-time error.
* Ukoliko potražimo adresu reference, vratiće adresu svoje "mete" (budući da predstavljaju alias nekog objekta [mete]).
* Reference se ne mogu menjati, u smislu da se dodele drugom objektu !!!
--> kada se definiše, referenca predstavlja alias samo za jedan objekat.
Pseudokod:
Citat:int intOne;
int &rSomeRef = intOne; //alias za intOne
....
int intTwo = 8;
rSomeRef = intTwo; // nije alias za intTwo !
// ova linija ce zapravo intOne dodeliti 8, referenca nece promeniti alias!
* Objekat može da bude NULL ukoliko iz nekog razloga ne može da se alocira memorija na heapu
--> budući da reference ne mogu biti NULL, dobra praksa defanzivnog programiranja je da se objekat provo proveri da li je NULL, i kada se utvrdi da nije NULL --> da se onda može incijalizovati referenca, da bude alias tom objektu.
Primer:
Citat:int *pObjekat = new Objekat();
if (pObjekat != NULL) { int &rObjekat = *pObjekat; }
|