Mis vahe on tulu väärtuse ja võrdluse alusel tagastamise vahel?


Vastus 1:

Teie olete funktsioon, mina olen funktsioon. Ütleme, et olete õunatarbija funktsioon, mina olen õunatarnija funktsioon. Ma hoian oma õunu ladustamisalal, kus on read ja veerud (või mis tahes muu organiseeritud skeem, mis jäljendab arvuti mälustruktuuri toimimist). Teie, tarbija, soovite õuna, nii et küsite minult, õuna tarnijalt. Selleks on mul veebisait ja vorm (funktsiooni liides). Kui minu ülesanne on tagastada väärtuse järgi, siis kui te minult õuna küsite, saadan teile tegeliku õuna ja see on teie enda teha nii, nagu soovite. Kui minu ülesandeks on naasta viite abil, siis ma ei saada teile õuna, ma annan teile oma õunahoidlasse koordinaatide, et saaksite minna ja võtta oma õuna (või süüa seda kohapeal).

Väärtuse järgi saate tegeliku asja. Viitena saate asjale… viite.


Vastus 2:

Oletame, et tagastatud andmed / objekt on funktsiooni ulatuses staatiliselt eraldatud.

Väärtuse järgi tagastamine tagastab andmete / objektide koopia, nii et see kutsub tagasi tagastatud objekti koopiakonstruktoriks (kui eksisteerib mõni koopiakonstruktor, sama kui siis, kui kasutame operaatori määramist = =). See koopia juhtub seetõttu, et tagastatav objekt hävitatakse (määratlemata) pärast funktsiooni ulatust (vt objekti eluiga), seega tuleb see tagastamise korral kopeerida. Helistaja ulatus (näiteks peamine) saab funktsiooni objekti või andmete koopia.

Näide:

// Tagasi val
Koer fooDog () {
    Koer koer ("Scooby"); // staatiliselt eraldatud koeraobjekt
    tagasta koer; // helistab koopia konstruktorileDog ja edastab selle helistajale
} // siia paigutatud koertehing

int main () {
    Koer myDog = fooDog (); // saab koera objekti koopia saidilt fooDog
    tagasi 0;
}

Tagastamine viite abil tähendab, et funktsiooni helistaja saab funktsioonilt andmeobjekti viite või aadressi. Kui andmed on staatiliselt eraldatud ja hävitatakse pärast funktsiooni ulatust, on selle objekti viide "rippuvad" või muul viisil viidatakse sellele kehtetule objektile. Seega ei ole funktsiooni staatiliselt eraldatud objekti puhul soovitatav viitega naasta.

// Tagasi ref
Koer & fooDogRf () {
    Koer koer ("Scooby"); // staatiliselt eraldatud koeraobjekt
    tagasta koer; // tagastab koera viite
} // siia paigutatud koertehing

int main () {
    Koer myDog = fooDogRf (); // saab koera viite funktsioonilt fooDogR, riputades ref cuz
    myDog.Bark (); // tõenäoliselt erand bad_alloci jaoks
    tagasi 0;
}

Oletame, et tagastatud andmed / objekt on dünaamiliselt eraldatud. Tagastamine viitega on turvalisem, kuna objekti eluiga ei ole funktsiooni ulatusega seotud, nii et viide ei ripu. Kuid hea C ++ programmeerijana peate vastutama dünaamiliselt eraldatud objekti puhastamise või selle asukoha määramise, nii et mälulekke ei juhtu.

Koer & fooDogR () {
    Koer * theDog = uus koer ("Gunner"); // dyn. alloc
    tagasi * theDog;
}

tühine optA () {
    Koer myDog = fooDogR ();
    myDog.Bark ();
    // kustuta & myDog; // seda võiks ka teha, kuna see on dünaamiliselt eraldatud, kuid see loob vea (kahekordsed tehingute asukohad)
} // minu koer paigutatakse siia turvaliselt

tühine optB () {
    Koer * pDog = & (fooDogR ());
    pDog.Bark ();
    kustuta pDog; // palju pDog
}

Ausalt, ma ei tea, mis on tagasitulek.

Loodan, et minu vastus aitab teid. Õnnelik kodeerimine.