Referințele în C++
Last Updated: Jun 03 2016 12:52, Started by
TheOriginals
, May 30 2016 16:42
·
0
#19
Posted 31 May 2016 - 10:46
C nu are suport nativ pt referinte (tipuri built-in) dar de ex. apelul functiilor cu parametri pointeri se cheama ca se face prin referinta la variabilele folosite ca argument.
dar cred ca pentru in incepator e prea confuz conceptul. |
#20
Posted 31 May 2016 - 11:11
&variabila - returnează adresă de memorie a variabilei. Valabil în C și C++.
tip date& variabila - declară o variabila referință cu tipul de date respectiv. Valabil numai în C++. De obicei folosești o referință: 1. Când o funcție trebuie să modifice o variabilă alocată în afara funcției și modificarea trebuie să fie vizibilă în afara funcției, exemplul dat de OriginalCopy. 2. Când o funcție lucrează cu o structură de date foarte mare. Dacă structura de date respectivă este transmisă prin valoare către funcție, mai întâi funcția face o copie privată a structurii de date, lucru care nu este de dorit întotdeauna , în special în cazul în care funcția nu modifică structura de date respectivă sau în cazul în care orice modificări făcute de funcție trebuie să se reflecte în varibila originală. Ca să dau un exemplu, poți avea un vector<int> cu 100000000 de elemente. Și poți avea o funcție care operează asupra unui vector<int> și numără câte numere impare sunt în vector, sau numere pare, sau află maximul, etc. Dacă transmiți vectorul prin valoare, adică vector<int>, fiecare funcție ar trebui să își facă o copie privată la vectorul de int, cea ce este ineficient, în condițiile în care nu modifică conținutul. Dacă în schimb folosești vector<int>& ca parametru la funcție, nu se copiază tot vectorul, doar referința, iar să copiezi o referență este mult mai rapid decât să copiezi 100000000 de elemente. De asemenea am putea avea o funcție care operează asupra unui vector<int> și înlocuiește fiecare apariție a numărului 13 din vector cu numărul 12, schimbarea trebuie să fie vizibilă în exteriorul funcției, deci este nevoie de o referintă, vector<int>&. |
#21
Posted 31 May 2016 - 11:19
o mica dar importanta corectie: nu se copiaza referinta la apelul functiei cu parametru referinta, ci se creaza o referinta care e un alias, un nume, o variabila cu un cost nesemnificativ fata de apelul prin valoare a unui super-obiect.
|
#23
Posted 31 May 2016 - 17:02
tavitu, on 31 mai 2016 - 11:11, said:
&variabila - returnează adresă de memorie a variabilei. Valabil în C și C++. tip date& variabila - declară o variabila referință cu tipul de date respectiv. Valabil numai în C++. int a=5; int&b=a;E chestia asta care ma scoate din minţi...in linia 2 ce se copie în b? adresa sau valoarea? Pentru că dacă am trata exact cum se vede acolo unei adrese îi atribuie o valoare, adică adresa lui b ar trebuie să fie 0x5 să zicem. |
#24
Posted 31 May 2016 - 17:18
nici, nici, e un detaliu de implementare ce e b in final.
pt tine e un alias, adica un alt nume pentru a. Similar cu TheO riginals, e un alias pt tine, cand eu string "bai TheO riginals!" te accesez pe tine tu esti obiectul propriu-zis catre care refera aliasul TheO riginals. Pe tine te cheama in buletin George sau Ion sau "a" dar pe forum folosesti un alias. int &b = a; inseamna declararea unui alias pt b, nu are a face cu adresa unui obiect, e o alta utilzare a ampersandului. de aceea cand zici "b" e ca si cum ai spune "a"; cand vine vorba de pointeri: int *p = &a; si p = &b; a si b vor fi practic acelasi lucru deci p va indica spre aceeasi variabila/locatie de memorie. la fel: a=2; si b=2; e fix la fel a=2; a ia valoare 2 b=3; tot a ia valoarea 3. Edited by andreim77, 31 May 2016 - 17:34. |
#25
Posted 31 May 2016 - 17:51
Mulţumesc omule...mi-ai luat o piatră de pe inimă în momentul de faţă,
Problema era că & îl vedem peste tot ca o adresă şi mi se pară ciudat că adresei i se atribuia o valoare. Acum am înţeles cum merge. Mersi încă o dată. |
#26
Posted 31 May 2016 - 18:17
Thefake_fake_fake, on 31 mai 2016 - 10:23, said: Din ce ştiu eu în C nu există referinţe dar totuşi se foloseşte &valoare. În C "&" are alt rol decât cel de referenţiere? Aici mă refer de exemplu la citirea Dar pe el, ca si pe cel din C++, il folosesti atunci cand apelezi o functie, nu in semnatura functiei, si are o semantica diferita. Din nou, trebuie sa faci diferentierea dintre "a citi o variabila" sau "a scrie intr-o variabila", analog cu ce ti-am spus ieri: in partea stanga a egalului te intereseaza adresa unei variabile, in partea dreapta te intereseaza valoarea ei. In exemplul de ieri in C++, & era in semnatura (antetul) functiei, aveai void max(int&), aici e vorba de referentiere. Aceasta sintaxa nu exista in C. pentru ca C nu are referinte asa cum sunt ele definite in C++. In C, la exemplul cu scanf, & il pui la apelarea functiei (aici: scanf), caci scrii: scanf("...", &a); --- observi unde e &? In ambele limbaje, & in operatiile de citire are aceeasi semantica: adresa unei variabile. int* a = &b; // salveaza in a valoarea lui &b, adica adresa la care e alocata static variabila b. void max(int&); /// nu este o sintaxa valida in C, doar in C++. Din nou, fa diferenta dintre operatiile de citire si de scriere. Acest &: int* a = &b; vs acest &: int& a = b; Sper ca observi ca sunt lucruri diferite. Reluand aceasta idee: OriginalCopy, on 31 mai 2016 - 18:13, said: analog cu ce ti-am spus ieri: in partea stanga a egalului te intereseaza adresa unei variabile, in partea dreapta te intereseaza valoarea ei. adica ori ca pui asa: int a = 42; ori asa: int a = b; in dreapta se afla o valoare. Intrebare: cum faci sa fortezi compilatorul sa evalueze ce e in dreapta ca adresa, nu ca valoare? Exact, pui &. int a = &b; Dar acum ai o problema: tipurile de date difera, in stanga ai int, in dreapta ai un intreg de marimea busului de adrese din CPU, deci ai in schimb: int* a = &b; Sper ca acum ti-ai mai dezvoltat intuitia fata de pointeri. |
#27
Posted 31 May 2016 - 18:19
Lol the fake fake fake
On: e un concept specific, aceeasi entitate folosita in diverse scopuri: & e folosit pt referinte, adresa unei variabile si ca operator si pe biti. Se cheama supraincarcare sau polimorfism static desi termenul asta e folosit mai mult in oop, dar mai ai pana ajungi acolo. |
#28
Posted 31 May 2016 - 18:47
Daca am int *p;
int x=3; Nu ştiu dacă e corect dar în mintea mea e o diferenţă între p şi *p; * e volosita pentru a afişa valoarea conţinută de adresa pointerului p. Dacă ii dau p=&x o să se modifice adresa conţinută de pe şi nu adresa lui p la care este stocat el nu? Am aici o imagine cum văd eu pointerii..e ok? [ http://s33.postimg.org/iig9lct1b/point.png - Pentru incarcare in pagina (embed) Click aici ] greenshot Mai ignoraţi din comentarii...am făcut desenul când mă chinuiam eu să înţeleg. Cand spre exemplu îi dai *p=&x, se modifica adresa care o contine p si o să indice spre x..dar când doreşti să-i afişezi valoarea faci tot cout<<*p; Adică când îl foloseşti = se modifică adresa conţinută de variabila de tip pointer, iar când foloseşti cout afişează valoarea conţinută de adresă...cu toate că în ambele cazuti foloseşti *p Edited by TheOriginals, 31 May 2016 - 18:52. |
|
#29
Posted 31 May 2016 - 19:02
"nu mi se pare corect sa folosesti *p = &a" - da, gandesti bine, nu se foloseste * in acel context, ci p = &a.
Greseala ta e ca lipesti (mental) * de variabila, si asta se vede si din cum formatezi codul. Acel * nu ii apartine variabilei, ci tipului de date. Daca te uiti la postarile mele, am scris mereu: int* p = &a; si nu: int *p = &a; Deoarece int* este un tip de date - il scriu impreunat. Ar trebui sa adopti acest stil de a formata codul, desi si int *p e corect, pana iti insusesti intuitia in mod corect. La fel si: int& a = b; e mai bine decat: int &a = b; <tip de date, oricare ar fi el> <identificator> = <valoare> e de fapt o scriere compacta pentru "doua" operatii: 1. alocarea statica a variabilei: <tip de date, oricare ar fi el> <identificator>; ex: int a; 2. copierea unei valori la acea adresa: <identificator> = <valoare> ex: a = 42; Asadar: int* p = &a; este prescurtarea pentru: int* p; p = &a; Acest mod de alipire a operatorilor unari gen * sau & de tipul de date e consistent si cu declararea de functii (doar antetul). In antet nu trebuie decat sa declari tipul de date, nu si identificatorul, deoarece dupa un antet nu mai urmeaza si implementarea functiei, ci direct ; int max(int*, int); int main() { //... aloca un array a de marime size) cout << max(a, size); return 0; } int max(int* data, int size) { // for loop over size memory cells of sizeof(int) starting at address data) //return maxim } |
#30
Posted 31 May 2016 - 19:15
Acum are mult mai mult sens, mai ales că mi-ai atras atenţia asupra chestiei cu int* a.
Mai am o chesti care nu îmi este clară: Am doua variabile x=5;// adresa lui x este 0x12 *p;//adresa lui p este 0x13 int* p = &a;//daca fac asta se traduce prin: adresa continută de p o sa fie = cu adresa lui a (adică noua adresă la care referă p o să fie 0x12) Adică cum văd eu chestia la momentul de faţă prin intermediul operatorului * s-a modificat adresa, dar când îl foloseşti în cout (cout<<*p) afişează valoarea. (După părerea mea se bat cap în cap..o dată prin intermediul * modific adresa spre care pointează variabila, iar când îl folosesc în cout afişează valoarea pointată de adresă) * se comportă diferit la cout? Adică de ce o dată prin intermediul * i-am modificat o adresă iar în cout el interpretează acea adresă şi afişează valoarea (în cauză fiind aceiaşi operator *)? |
#31
Posted 31 May 2016 - 19:17
Quote Daca am int *p; int x=3; Nu ştiu dacă e corect dar în mintea mea e o diferenţă între p şi *p; * din int *p; e total altceva decit * din *p Vezi tu, limbajul asta e cretinel in esenta lui, de fapt este int* p; adica "pointer la int" dar el, limbajul cretinel, permite sa scrii acel gunoi de asterisc oricum int* p; int * p; int *p; chiar si int * p; toate sint valide, pentru ca Satan, creatorul limbajului, a vrut sa-l faca cit mai imposibil pentru incepatori... Cica motivul pentru care se foloseste asa de mult varianta cu asterisc linga variabila in loc de tip este ca daca declari mai multe variabile pe aceeasi linie si nu pui linga fiecare cite un asterisc, doar prima e pointer, adica int* a, b, c; // doar a e pointer int *a, *b, *c; // toti este ponteri (limbaj de manelist) Deci ca sa revenitm tu cind zici int * p = 3 nu e nici pe departe ce zici tu in imaginea aia, nici macar nu compileaza... incerci sa atribui un "int" unui "pointer la int" Ca sa faci ce vrei tu tre sa faci: int* p = new int; *p = 3; Pe de alta parte, * din *p se numeste dereference operator, dracu stie cum se traduce asta in romana, si face ce zici tu in imaginea aia... |
#32
Posted 31 May 2016 - 19:31
Eu zic sa bagi pe google: ted jensen pointers tutorial si sa iei la rand toate exemplele de acolo si - foarte important - sa le tastezi tu cu mana ta de la zero, pentru ca in timp ce tastezi cod intelegi altfel ce cod scrii, si sa nu dai copy/paste la cod.
Unul din exemplele din acel tutorial este de genul: 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main() { 5 int* p; 6 int a; 7 printf("variable a is allocated statically at address %p and has garbage value %d\n", &a, a); 8 printf("variable p is allocated statically at address %p and points to garbage address %p\n", &p, p); 9 //copying value 42 to address &a 10 a = 42; 11 // store the value &a at address &p 12 p = &a; 13 printf("variable a is allocated statically at address %p and has value %d\n", &a, a); 14 printf("variable p is allocated statically at address %p and points to address %p\n", &p, p); 15 printf("now it is safe to dereference pointer p because it does not point to garbage: %d\n", *p); 16 return EXIT_SUCCESS; 17 } 18 Fii foarte atent la valori si fa corelatii. Atentie la ce ti-am spus ieri: toate sunt variabile, pointerii sunt in primul rand variabile, referintele la fel. Si ti-am mai spus si ca toate variabilele au o adresa, un identificator, o valoare, si un tip de date. ASADAR, si pointerii au o adresa. PS: in realitate compilatorul poate face tot felul de optimizari, insa ele sunt irelevante pentru ca tu ca incepator sa intelegi cum functioneaza lucrurile - ba mai mult te-ar incurca in procesul de intelegere. Edited by OriginalCopy, 31 May 2016 - 19:36. |
#33
Posted 31 May 2016 - 19:35
Ok, asta e cartea https://pdos.csail.m...gs/pointers.pdf ?
|
|
#34
Posted 31 May 2016 - 19:58
Thefake_fake_fake, on 31 mai 2016 - 19:35, said:
Ok, asta e cartea https://pdos.csail.m...gs/pointers.pdf ? |
#35
Posted 31 May 2016 - 20:05
ok, cred că am înţeles, oricum am să citesc ce mi-ai lăsat pentru că din ce văd e explicat şi bine şi nici nu e voluminoasă.
Mersi //update ) Tu-i în aripă de pointeri..pot să spun că tocmai s-a făcut lumină. Acum sper să nu vă mănânc nervii şi mâine cu întrebări după ce termin de citit cartea. ) Edited by TheOriginals, 31 May 2016 - 20:25. |
#36
Posted 01 June 2016 - 09:44
Quote adica "pointer la int" dar el, limbajul cretinel, permite sa scrii acel gunoi de asterisc oricum c++ e un limbaj f puternic, probabil cel mai complex, care iti permite sa faci orice dar si sa distrugi orice daca nu ai grija. Si C permite acelasi lucru. ia uite de ex. cum arata man strcpy in linux: #include <string.h> char *strcpy(char *dest, const char *src); char *strncpy(char *dest, const char *src, size_t n); Mai exact unde au pus steluta. Iar baietii care au scris linux si man sunt mai destepti ca noi. Accentul e pe faptul ca variabilele sunt pointeri. Un argument egal cu al tau, ca vrei tipul complet scris compact. E aceeasi discutie ca while(*p++ == *q++) {}, unora le place altora nu, dar cine pricepe subtilitatile limbajului indeajuns, va sti valoarea unei astfel de expresii. Steluta poate fi pusa oriunde, langa tip, variabila sau cu spatii intre ambele pt ca limbajul e "free form", asa cum cred ca e orice limbaj de nivel inalt. Prin nivel inalt nu se intelege ca-i valoros ci e apropiat de limbajul uman (nu am alta explicatie mai clara acum ). Edited by andreim77, 01 June 2016 - 09:45. |
Anunturi
Bun venit pe Forumul Softpedia!
▶ 0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users