...
...
...
...
...
int main() {
...
int x;
...
cin >> x; // scanf("%d", &x);
...
double y;
...
cin >> y; // scanf("%lf", &y);
...
char z[20];
...
cin >> z; // scanf("%s", z);
...
}
Fără a intra acum în detalii menţionăm că operatorii << respectiv >> pot fi aplicaţi înlănţuit. Deci de exemplu
int w;
...
cout << "w = " << w + 25 << '\n';
este echivalent cu
int w;
...
printf("w = %d\n", w);
Trecerea la linie nouă se poate efectua şi cu
cout << endl;
Deci în loc de apelarea funcţiei printf de mai sus, s-ar fi putut scrie şi:
cout << "w = " << w + 25 << endl;
Există o diferenţă minoră dintre limbajele C şi C++, referitoare la constantele de tip caracter. Ele sunt memorate pe doi octeţi în limbajul C şi au tipul int. În limbajul C++ însă există două feluri de constante de tip caracter. Memorate pe un octet ele au tipul char, iar pe doi octeţi au tipul int.
Să considerăm următorul exemplu. Fişierul caracter.cpp:
După executarea programului se obţine:
Observăm că într-adevăr caracterul 'AB' este de tip int şi în octetul mai semnificativ este memorat codul ASCII al caracterului 'B', iar în cel mai puţin semnificativ codul ASCII al caracterului 'A'.
În limbajul C utilizarea operatorului de conversie explicită se face sub forma:
(tip) expresie
În limbajul C++ operatorul de conversie explicită se poate aplica şi în modul următor:
tip(expresie)
Să considerăm următorul exemplu. Fişierul conv1.cpp:
După executarea programului obţinem:
Rezultă că într-adevăr s-a realizat conversia variabilei x de la tipul double la tipul int, şi conversia variabilei p de la tipul void* la tipul double*. Menţionăm că în acest caz, introducerea tipului p_double a fost obligatorie. Dacă s-ar fi folosit conversia explicită (double*) p, atunci nu ar fi fost necesar definirea tipului p_double.
În limbajul C++ putem defini şi conversii utilizator ataşate unor tipuri definite de programator. Conversiile utilizator se vor trata în secţiunea 16.8.
15.2. Operatori
15.2.1. Operatorul de rezoluţie
Dacă o dată globală se redefineşte într-o funcţie, atunci referirea la data globală se poate face cu ajutorul operatorului de rezoluţie. Numele datei globale trebuie precedată de caracterele ::, deci de operatorul de rezoluţie.
Prezentăm în continuare un exemplu. Fişierul rezol.cpp:
Deci se observă că referirea la variabila globală x de tip int s-a făcut cu ajutorul operatorului de rezoluţie (::x ). Menţionăm că operatorul de rezoluţie se va folosi şi în cazul în care se face referire la datele respectiv funcţiile membru ale unei clase.
15.2.2. Folosirea operatorului adresă pentru definirea tipului referinţă
În limbajul C operatorul & se foloseşte pentru a determina adresa unei variabile. În limbajul C++ acest operator mai este folosit şi pentru definirea tipului referinţă. Am văzut că în cazul pointerilor construcţia
reprezintă un tip pointer. La fel şi în cazul de faţă prin
se va înţelege un tip referinţă. Cu ajutorul tipului referinţă putem defini nume alternative pentru date deja cunoscute. Aceste nume alternative pot fi utilizate în continuare în locul datelor respective. Deasemenea acest tip de date se va folosi şi pentru realizarea apelului prin referinţă în limbajul C++.
Dacă se foloseşte ca şi parametru formal într-o funcţie, atunci tipul referinţă va fi de forma:
tip & parametru_formal
iar declararea unei variabile de tip referinţă se va face sub forma
tip & nume = dată;
Exemplu. Fişierul
refer1.cpp.
Observăm că aceeaşi zonă de memorie este accesată în trei feluri. Primul element al vectorului x este x[0], y este referinţă la acest element, deci un nume sinonim pentru x[0], iar z este un pointer către vectorul x, astfel *z reprezentând acceaşi zonă de memorie ca şi x[0]. Rezultă că valoarea oricărei dintre aceste trei elemente s-ar schimba, valorile celorlalte se schimbă în mod automat.
Există posibilitatea definirii unei referinţe şi la o funcţie. Acest lucru este prezentat în exemplul următor. Fişierul refer2.cpp:
În exemplul de mai sus s-a declarat o referinţă la funcţia standard de bibliotecă sin, deci numele sinus poate fi folosit în locul funcţiei sin pentru a calcula sinusul unui număr real.
Tipul referinţă este cel mai des folosit pentru realizarea apelului prin referinţă, ceea ce se tratează în paragraful următor.
15.2.3. Apelul prin referinţă
În limbajul C apelul este prin valoare. Acest lucru înseamnă că parametrii actuali şi cei formali sunt memorate în diferite locaţii de memorie. La apelarea funcţiei parametrii actuali îşi transmit valoarea lor parametrilor formali corespunzătoare. De aceea modificarea parametrilor formali nu are nici un efect asupra parametrilor actuali. Următorul exemplu scris în limbajul C ilustrează acest lucru. Fişierul valoare1.cpp:
Constatăm că într-adevăr parametrul actual y nu se modifică, şi programul afişează valoarea 10.
Totuşi şi în limbajul C se poate realiza modificarea parametrilor actuali, cu ajutorul pointerilor. Acest lucru este prezentat în următorul exemplu.
Fişierul valoare2.cpp:
În exemplul de mai sus s-a realizat modificarea valorii parametrului actual y, dar şi în acest caz s-a folosit de fapt apel prin valoare. S-a transmis valoarea adresei lui y pointerului x. Deci prin intermediul pointerilor apelul prin valoare s-a transformat în apel prin referinţă. Menţionăm că numele unui vector de elemente este un pointer către primul element al vectorului. În consecinţă, dacă un parametru actual este un vector, atunci valorile elementelor acestui vector pot fi modificate în interiorul funcţiei.
Această modalitate de realizare a apelului prin referinţă, prin intermediul pointerilor, de multe ori îngreunează munca programatorului, de aceea în limbajul C++ s-a introdus şi apelul prin referinţă propriu zis.
Apelul prin referinţă se realizează cu ajutorul tipului referinţă. În cazul folosirii tipului referinţă parametrul formal este un nume alternativ pentru parametrul actual, deci ele reprezintă aceeaşi zonă de memorie şi ca atare orice modificare a parametrului formal conduce la modificarea parametrului actual corespunzător. Iată cum se modifică exemplul de mai sus folosind apelul prin referinţă. Fişierul refer3.cpp:
Putem constata că apelul prin referinţă este mult mai simplu de utilizat, decât realizarea ei prin intermediul pointerilor.
15.2.4. Operatori pentru alocare şi dezalocare dinamică a memoriei
Pentru alocare şi dezalocare de memorie în limbajul C pot fi folosite funcţiile malloc şi free. În limbajul C++ există şi operatori pentru realizarea acestui lucru.
Alocarea memoriei se poate face folosind operatorul new, în unul din următoarele trei moduri:
-
new tip
-
new tip(expresie_1)
-
new tip[expresie_1]
În toate cele trei cazuri construcţiile de mai sus formează o expresie pe care o vom nota cu expresie_2. Valoarea expresiei expresie_2 este egală cu adresa de început a zonei de memorie alocate, şi este zero în cazul unei erori.
În cazul a) se alocă zonă de memorie pentru o variabilă de tipul exprimat prin tip. În cazul b) zona de memorie alocată se iniţializează cu valoarea expresiei expresie_1, iar în cazul c) se alocă memorie un număr de expresie_1 de zone de memorie de tipul menţionat. Deci în cazul a) şi b) se vor aloca un număr de sizeof(tip) octeţi, iar în cazul c) expresie_1 * sizeof(tip) octeţi.
În tabelul 1 prezentăm trei exemple de secvenţe de programe echivalente, în care se foloseşte operatorul new în diferite moduri.
Eliberarea zonei de memorie alocate cu operatorul new se va face cu ajutorul operatorului delete. Să considerăm pointerul q pentru care s-a alocat memorie folosind operatorul delete.
Dacă alocarea zonei de memorie s-a făcut cu una din variantele a) sau b) atunci dezalocarea se va face în forma:
delete q;
iar dacă alocarea s-a făcut prin varianta c) atunci eliberarea zonei de memorie se va face cu
delete [expresie_1] q;
unde
expresie_1 este expresia care s-a folosit la alocare. De obicei ea poate să lipsească.
-
Nr. crt.C++C sau C++double* d;
d = new double;double *d;
-
d = (double *) malloc(sizeof(double));int* i;
i = new int(20);
int* i;
i = new int;
-
*i = 20;double* p;
p = new double[10];d = (double *) malloc(10 * sizeof(double));
Tabelul 1: folosirea operatorului new
Dostları ilə paylaş: