Rozdíl mezi referencí (&) a dereferencí (*) – C++ – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Rozdíl mezi referencí (&) a dereferencí (*) – C++ – C / C++ – Fórum – Programujte.comRozdíl mezi referencí (&) a dereferencí (*) – C++ – C / C++ – Fórum – Programujte.com

 

RePRO0
Super člen
6. 3. 2012   #1
-
0
-

Zdravím,
mohl by mi někdo vysvětlit rozdíl mezi těmito třemi funkcemi?
(http://pastebin.com/5M6jB7fL)
Programuji už léta, vždy jsem využil dereferenci. Ovšem, tady jsou tři funkce a v parametrech je jak reference (&) a dereference (*). Návratové hodnoty jsem taky změnil.
Všechno mi šlo přeložit (IDE: Microsoft Visual C++).

Vždycky jsem měl problémy, co se může dávat za parametry, takže to shrnu:

Pokud máme proměnnou dereferenci: *ukazatel

  1. funkce(*prom) – dáváme: funkce(ukazatel)
  2. funkce(&prom) – dáváme: funkce(*ukazatel)

Pokud máme proměnnou klasiku: klasika

  1. funkce(&prom) – dáváme: funkce(klasika)
  2. funkce(*prom) – dáváme: funkce(&klasika)

Nebo jsou i jiné možnosti?

Moje otázky
1) Jaký je tedy rozdíl mezi referencí a dereferencí? Přijde mi to dosti analogické. Můžu si stále používat dereferenci?
Jakožto reference je adresa proměnné, dereference je též adresa proměnné, akorát na ní směřuje ukazatel.
2) Jaký je rozdíl mezi druhou a třetí funkcí?

Doufám, že si už v tom udělám absolutní jasno, i když ho mám, ale ne zcela úplné. Dobrý programátor toto prostě musí umět dokonale – aneb práce s pamětí.
Tímto bych chtěl i pozdravit kolegu a kámoše Matrixe, pokud si toto vlákno čte a hodí mi sem třeba i dobrou radu nad zlato. ;-)

Díky a mějte se – pěkný den.

Nahlásit jako SPAM
IP: 95.82.185.–
Software: C; C++; C#; Pascal; Delphi; Java Webdesign: PHP; MySQL; CSS; jQuery; Ajax; Javascript; OOP
KIIV
~ Moderátor
+43
God of flame
6. 3. 2012   #2
-
0
-

1) reference znamena ze se vytvori odkaz na nejakou promennou ...  tj. napriklad  &promenna -> ukazatel na misto kde je ta promenna

dereference je opak - kdyz mas adresu a chces ziskat jeji hodnotu

ma to ale hacek - u prototypu funkci se to chova trosku jinak:

void funkce( int * ukazatel)  {  *ukazatel += 1; }  a volame:  int cislo=10;  funkce(&cislo);   -> cislo == 11;  

void funkce( int & reference ) { reference +=1; } a volame:  int cislo=10;  funkce(cislo);  -> cislo == 11;

a na zaver:

void funkce( int nejaky_cislo) { nejaky_cislo+=1; } volame  int cislo=10;  funkce(cislo);  ->  cislo zustava 10 (zmenila se jen lokalni promenna ve funkci

2)  rozdil mezi druhou a treti je v tom, ze druha vraci vesmes stale ten samy objekt (tj bod) a treti udela kopii a tu vrati  (nebo neco v tom smyslu)

Nahlásit jako SPAM
IP: 94.112.32.–
Program vždy dělá to co naprogramujete, ne to co chcete...
RePRO0
Super člen
6. 3. 2012   #3
-
0
-

Tak nějak s Tebou úplně nesouhlasím. Napsal si 2 typy, co dosazuješ za parametry. Vždy ale záleží na tom, co máš za výchozí proměnné:

1)
výchozí proměnná: *ukazatel
void funkce(&reference) { ... };
potom: funkce(*ukazatel);

2)
výchozí proměnná: normální
void funkce(*dereference) { ... };
potom: funkce(&normální);

3)
výchozí proměnná: normální
void funkce(&reference) { ... };
potom: funkce(normální);

4)
výchozí proměnná: *ukazatel
void funkce(*dereference) { ... };
potom: funkce(ukazatel);

Navíc si myslím, že "*" a "&" pracuje naprosto stejně - uvnitř je pointerová logika. Myslím, že největší rozdíl tkví v tom, že

  • "&" (reference) nepřiřadíme NULL a těžko se mění,
  • "*" (dereference) se přiřadí NULL a změní se kdykoliv (krom const).

Ty funkce budou fungovat analogicky. Jde pouze o syntakční stránku.

 

Nahlásit jako SPAM
IP: 95.82.185.–
Software: C; C++; C#; Pascal; Delphi; Java Webdesign: PHP; MySQL; CSS; jQuery; Ajax; Javascript; OOP
yaqwsx+9
Posthunter
6. 3. 2012   #4
-
0
-

Přijde mi, že si trochu pleteš pojmy. Slovo dereference bych přímo nepoužíval - spíše bych použil sloveso dereferencovat, popř. spojení operátor dereference. Žádné předávání dereferencí není.

Trochu ukázky na příkladech:

void mojefunkce1(mujtyp a);//Proměnnou předávám pomocí kopie
void mojefunkce2(mujtyp* a);//Předávám ukazatel na proměnnou
void mojefunkce3(mujtyp& a);//Předávám referenci na proměnnou

Reference je v podstatě ukazatel, o který se stará komplátor (tzn. uživatel si nemusí hlídat paměť - vhodné pro předávání do funkcí) a proto je omezený - např. vždy musí mít inicializovanou hodnotu, nefunguje u něj ukazatelová aritmetika a pod.

Tohle je asi jasné. Problém je v tom, že operátor * má více funkcí - záleží na tom, kde se nachází. Pokud se nachází v deklaraci, tak vytváří pointer. Pokud se nachází před již vytvořeným ukazatelem, dereferencuje pointer a umožní ti přistoupit k datům, na která pointer ukazuje.

int* a;//Ukazatel na int se jménem a
a = 125865;//Uloží adresu do pointeru - tato operace je v praxi nesmyslná
(*a) = 5;//Uloží do paměti na kterou ukazuje ukazatel a číslo 5; operátor * zde derferencoval pointer a
Nahlásit jako SPAM
IP: 85.160.61.–
Life is too short to remove USB mass storage safely...
Správný drsňák udělá z konzole cokoliv
RePRO0
Super člen
6. 3. 2012   #5
-
0
-

Díky. Ještě přidávám ukázku bez funkcí:

U funkcí (a metod) mi přijde nejběžnější a nejlogičtější předávat referenci, pokud je přímo v definici funkce dereference.

	int a = 5;
	int *ukazatel = &a;
	// Vypíše adresu, kam ukazuje (tedy adresu obsahu)
	cout << ukazatel << endl;
	// Vypíše obsah, kam ukazuje ukazatel
	cout << *ukazatel << endl;
	// Vypíše adresu samotného ukazatele
	cout << &ukazatel << endl;
Nahlásit jako SPAM
IP: 95.82.185.–
Software: C; C++; C#; Pascal; Delphi; Java Webdesign: PHP; MySQL; CSS; jQuery; Ajax; Javascript; OOP
RePRO0
Super člen
6. 3. 2012   #6
-
0
-

A pokud předáš ukazatel, proč by to nešlo? Resp. předá se adresa.

Nahlásit jako SPAM
IP: 95.82.185.–
Software: C; C++; C#; Pascal; Delphi; Java Webdesign: PHP; MySQL; CSS; jQuery; Ajax; Javascript; OOP
crazy
~ Moderátor
+10
Grafoman
6. 3. 2012   #7
-
0
-

#5 RePRO
dereference v definici funkce? co to znamenená? 

Nahlásit jako SPAM
IP: 2001:718:2:31:1e75:8ff:fe...–
All you need is vision and time.
KIIV
~ Moderátor
+43
God of flame
6. 3. 2012   #8
-
+2
-
Zajímavé

v definici funkce to neni samozrejme dereference...  

typ funkce( typ * promenna); ==  rikam prekladaci: bude funkce ktera vraci "typ" a ocekava ukazatel na jednu nebo libovolne mnozstvi dat typu "typ"

je to to same jako

int * pointer;  tady to taky neni dereference, ale oznaceni typu "ukazatel na typ int"

Nahlásit jako SPAM
IP: 94.112.32.–
Program vždy dělá to co naprogramujete, ne to co chcete...
RePRO0
Super člen
6. 3. 2012   #9
-
0
-

crazy:

V parametru funkce máme ukazatel na int (*). Ve volání funkce pak očekáváme adresu proměnné (&).

Ukazuji ještě druhou možnost, kdy můžeme vrátit ukazatel na nově alokovanou paměť, kde máme výsledek.

:-)

int scitani1(const int *ax, const int *bx) {
    
    return *ax + *bx;
};

int* scitani2(const int *ax, const int *bx) {
    
    return new int(*ax + *bx);
};

int main(int argc, char *argv[])
{ 
  int a = 5;
  int b = 2;

  cout << scitani1(&a, &b);
  
  int *c = scitani2(&a, &b); 
  cout << *c << endl;
  delete c;
        
  system("PAUSE");    
  return 0;
}

Pro takto jednoduché věci jsou pointers zbytečné, ale... jenom pro demonstraci. :-)

Nahlásit jako SPAM
IP: 95.82.185.–
Software: C; C++; C#; Pascal; Delphi; Java Webdesign: PHP; MySQL; CSS; jQuery; Ajax; Javascript; OOP
crazy
~ Moderátor
+10
Grafoman
6. 3. 2012   #10
-
0
-

#9 RePRO
nějak jsem nepochopil, co se nám tím snažíš ukázat...

Nahlásit jako SPAM
IP: 2001:718:2:31:1e75:8ff:fe...–
All you need is vision and time.
KIIV
~ Moderátor
+43
God of flame
6. 3. 2012   #11
-
+1
-
Zajímavé

no ber to takhle: v C reference nebyly a pokud si chtel predat do funkci promenne, ktere se mely zmenit i vne funkce, musel si vzdy pouzivat dereferenci (uvnitr funkce - ne uvnitr prototypu)

v C++ uz jsou i reference -> ma to svoje vyhody i nevyhody - pri volani nepoznas, zda se parametr muze uvnitr menit ... u C si mel proste   &promenna nebo si predaval rovnou pointer... zase si lze usetrit dereference protoze se to tvari jako lokalni promenna ale meni i tu vnejsi

Nahlásit jako SPAM
IP: 94.112.32.–
Program vždy dělá to co naprogramujete, ne to co chcete...
RePRO0
Super člen
7. 3. 2012   #12
-
0
-

KIIV:

Díky. Poslední věc... Ještě by mě zajímalo v jakých případech použít pointers a kdy ne? Já je používám skoro všude (C/C++), ale v C# je to dosti omezující, tam to musím házet do sekce [unsafe].

Btw: Někdy fakt magořím, co kam použít... [*], [&], [->], [.]. Ještě, že existuje IntelliSense. Bez toho ani krok... Co používáš pro vývoj C/C++? Pro školní projekty tu mám Dev-C++ (Grr). Jinak pro profi vývoj Code::Blocks a Microsoft Visual C++.

Ještě jedno btw. Jak se jmenuje ten třetí a čtvrtej operátor?  Mám za to, že ten třetí je operátor přístupu k prvku struktury nebo unionu s dereferencí. No a čtvrtej analogicky operátor přístupu k členu struktury nebo unionu. To víš, chci mít ve všem jasno.

Měj se.

RePRO

Nahlásit jako SPAM
IP: 95.82.185.–
Software: C; C++; C#; Pascal; Delphi; Java Webdesign: PHP; MySQL; CSS; jQuery; Ajax; Javascript; OOP
KIIV
~ Moderátor
+43
God of flame
7. 3. 2012   #13
-
+1
-
Zajímavé

Na to, kdy co pouzit, je horsi odpovedet - vseobecne pointery hlavne na dynamickou pamet, na predavani odkazem v C++ asi reference (a v C neni na vyber - jen pointery). No a kdyz nepotrebujes menit promenne i venku tak predani hodnotou (alias kopie)

U pointeru je vzdy dulezity pamatovat u kopirovani a podobnejch akci, ze se kopiruje jen odkaz(adresa) ale ne data - tj. kdyz se navrhne blbe program, muze to delat peknou paseku. V C++ je pak lepsi pouzivat objekty a pohlidat si vsechny akce vcetne kopirovani a tak.

V C# je urcite mozne rozjet vse i bez pointeru... co bys delal treba v PERLu? kde jsou jedine referencni typy a to jen takovy pseudo... realnej pointer tam neexistuje.

Kdyz mam pointer tak pro upravu adresy staci pricitat/odcitat, pro upravu hodnoty se musi bud dereferencovat  *(addr+offset) nebo addr[offset], a samozrejme pokud chceme menit ve funkci i velikost alokovaneho pole, musi se predat adresa, kde je pointer ulozen (jinak by se jen zmenila lokalni kopie adresy ale nedostala by se uz z funkce do volajici casti)

A pristupy k prvkum/metodam struktury/objektu se pouziva . pro typy ktere nejsou ukazatele! Pro ukazatele na struktury nebo objekty se musi pouzit pristup dereferencovany ->  (dereferencuje pointer a pristoupi k nejakemu prvku) - nicmene jde pouzit i:   (*ukazatel).prvek nebo ukazatel[0].prvek (misto  ukazatel->prvek)

BTW: na vsechno programovani uz pouzivam jedine gvim / vim - intelisense to nema, takze vse musim ohlidat sam (pripadne podle chybovych hlasek)

Nahlásit jako SPAM
IP: 94.112.32.–
Program vždy dělá to co naprogramujete, ne to co chcete...
vitamin+8
Grafoman
7. 3. 2012   #14
-
+1
-
Zajímavé

Referencie su v podstate obmedzene pointre. 

Ciel referencie sa moze nastavyt len pri inicializacii, neskor sa uz neda menit. V kode sa s referenciou pracuje ako s obycajnou premennou (z pohladu syntaxe).

Podla mna vznikly referencie hlavne kvoly kopirovacim konstruktorom a pretazenym operatorom kde by sa s pointrami pracovalo dost blbo.

Este existuje rvalue referencia, syntax ma nasledovnu:

void funkcia(int && rvalue_ref);

Tato referencia moze ukazovat na rvalue, pouziva sa to pri move konstructoroch a predpoklada ze premenna na ktoru ukazuje sa uz nebude dalej pouzivat.

Nahlásit jako SPAM
IP: 178.143.60.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 72 hostů

Podobná vlákna

Rozdíl mezi == a is — založil Ahoj3

Rozdíl mezi C, C++ a C# — založil Murmand

Rozdil mezi class a id — založil Václav Žitek

Rozdil mezi endl a \n — založil MyName

Rozdíl mezi zápisy — založil Tomas

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý