|
[ Valerij Zajcev @ 07.07.2007. 20:10 ] @
| literatura koju koristim je na engleskom pa nisam bas 100% siguran u neke stvari, a reference mi deluju najkomplikovanije do sada..
Dobro za vrednosne tipove sam razumeo oni sadrze vrednosti direktno, ali referentni tipovi me ubise.
"...kada deklarisete promenljivu krug kompajler ne genirise kod koji alocira memoriju za krug vec joj samo dodeli mali deo memorije koji ce pokazivati na adresu (reference to) drugi blok memorije koji sadrzi krug..."
..."memorija za objekat krug je alocirana kada se iskoristi new da se napravi objekat..." ovde me zbuni cas prica o krugu kao klasi, a onda o objektu krug?!
Da ne zamaram uglavnom moze li neko da me uputi da bar znam na sta da obracam posebno paznju kad ucim o ovome, ili ukratko da mi objasni sta su reference (cemu sluze)? |
[ Valerij Zajcev @ 07.07.2007. 21:40 ] @
nije da se ne trudim...
imam klasu student(ime(), prezime(), index()...)
kada u programu napravim >>student vlada;<< ovde se zbunim, da li se u memoriji vec nalazi klasa student, i objekat vlada je rekao klasi mozda cu da te iskoristim, iz cega sledi:
>>vlada = new student()<< predpostavljam da je ovo sada onaj deo u kome je promenljivi vlada zauzeo memoriju u celosti koliko mu pripada.
Posle ovoga vlada sadrzi referencu na clanice klase student i moze da ih koristi:
vlada.ime = "pera";
vlada.index = 12345;
???
[ Gosovic @ 07.07.2007. 22:18 ] @
Iz klase se prave objekti. Klasa sama za sebe ne zauzima nikakvu memoriju.
Dakle, imas klasu 'student' i od nje napravis dva objekta
vlada = new student()
pera = new student()
ta dva objekta su medjusobno nezavisna, svaki trosi memoriju za sebe i imaju istu funkcionalnost
Sto se tice referenci, za objekte vlada i pera referenca je klasa student. Bez nje ni oni ne mogu biti kreirani.
[ spartak @ 08.07.2007. 08:25 ] @
Nisam siguran da si mu tacno objasnio.
MojaKlasa prva = new MojaKlasa(); // zauzeta memorija
MojaKlasa druga = prva; // referenca na prvu
Sada kad na prvoj promenis recimo prva.Ime = "Test" pa pozoves druga.Ime dobices "Test" ponovo. Ista memorijska lokacija, prva je zauzela a druga referencira prvu.
[ Gosovic @ 08.07.2007. 09:14 ] @
Slazem se da nisam dovoljno pazljivo procitao pitanje, ja sam mislio na reference koje se dodaju projektu.
U vezi pitanja Valerij Zajcev-a, mozda moze ovo da pomogne
http://msdn2.microsoft.com/en-us/library/aa903254(VS.71).aspx
[ maksvel @ 08.07.2007. 11:09 ] @
Vrednosni tipovi se čuvaju na stek memoriji, koja je relativno mala. Zato se u njoj ne čuvaju objekti, već samo reference, dok se "pravi" objekti nalaze na heap memoriji - veeelikom skladištu.
Kada kaže "za objekat krug", misli na "objekat tipa krug", na konkretan krug, koji je inicijalizovan sa nekim vrednostima (npr. centar i poluprečnik). Sa new se alocira memorija na heap-u, a kasnije je "puniš" podacima objekta.
[Ovu poruku je menjao maksvel dana 08.07.2007. u 14:01 GMT+1]
[ Valerij Zajcev @ 08.07.2007. 13:55 ] @
Code: {
krug c;
c = new krug(42);
krug refc = c;
Console.WriteLine(c);
Console.WriteLine(refc);
}
A sta mi znaci izlaz ovoga?
output
Code: reference.krug
tj. zasto ne dobijam vrednosti 42, i da li shvatam sustinu referenca treba da pokazuje na neki drugi objekat i na njegove vrednosti?
edit
Postajem dosadan, ako imam neku promenljivu sa nekom vrednostu, i prosledim je kao parametar nekom metodu i on ga obradi (primer prosledim i, a u metodi imam i++) nije se promenio glavni parametar ali ovaj u metodu ostaje isti, ako je ovo ispravno zasto bih ja ovo kog djavola radio???
[Ovu poruku je menjao Valerij Zajcev dana 08.07.2007. u 15:25 GMT+1]
[ toxi_programer @ 08.07.2007. 17:20 ] @
Pa vidiš postoje referencijalni i vrednosni tipovi podataka. Postoje i pointerski al to sad nije bitno.
Svaki objekat klase kojeg u C# jeziku napraviš je referencijalan. Vidi ovako:
Student pera = new Student();
Student djoka = pera;
pera.Godine = 20;
U prvoj liniji se( pomoću "new") rezerviše određeno mesto u heap-u za novi objekat koji je tipa "Student" i vraća se referenca na taj novokreirani objekat. Zatim se u ref. "pera"smešta rešerenca na taj novokreirani objekat. Na ovaj način ti možeš da pristupiš memoriji na heap-u na kojoj se nalazi novokreirani objekat i da mu menjaš vrednosti( to je ono iz treće linije koda).
U drugoj liniji si napravio novi referencijalni tip koji se zove "djoka" i postavio ga da "pokazuje" na isto mesto u memoriji na koje pokazuje i "pera". Samim tim, oni koriste istu memoriju pa ako promeniš "Godine" pomoću "pera" onda će i "djoka" da ima isto 20 godina...
Nasuprot referencijalnim tipovimam postoje već pomenuti vrednosni. To su int, float, double i ostali ugrađeni( string je referencijalni ali se ponaša kao vrednosni). Oni se smeštaju na stek, pa ako napišeš:
Code:
int x, y; //napravio si dva nova objekta, nedodelivši im nikakvu vrednost
x = 15; //dodeljuješ vrednost prvom objektu
y = x; //KOPIRAŠ prvi objekat u drugi, nema nikakvih referenci i zato su oni potpuno "razdvojeni( svaki ima svoju memorijsku lokaciju koju koristi)
y = 69; // dodeljuješ vrednost promenljivoj Y, a pošto ona ne koristi istu memoriju kao i X, X će imati staru vrednost a to je 15
[ Valerij Zajcev @ 08.07.2007. 18:29 ] @
dobro sad mi je to jasno, samo mi jedno ne deluje logicno:
ako ja mogu da uradim
pera.godine = 5; //onda pera ima 5 godina
djoka.godine = 6; //onda i pera i djoka imaju po 6 godina jel da?
moje pitanje je cemu onda djoka ako godine mogu da se promene i preko pere, zasto bih bilo sta od toga radio???
[ Java Beograd @ 08.07.2007. 18:54 ] @
Hm, ajde da vidimo da li si shvatio.
Ako je
Student pera = new Student();
Student djoka = new Student();
pera.Godina = 3;
djoka.Godina = 2;
onda svako ima svoje godine i nema frke;
Ali ako :
Student pera = new Student();
Student djoka = pera;
pera.Godina = 3;
onda je ovde i djoka na trecoj godini. Naravno, ovo je sasvim zvezebe i nemas potrebe da ovo radis. Mislim, mozes, ali sta ce ti dve promenljive, tj. dve reference na isti objekat.
Mozda ces lakse i lepse da svaris te reference na sledeci nacin:
Student pera = new Student();
PostaviOsnovneVrednosti(pera);
// 1
.
.
.
.
.
private void PostaviOsnovneVrednosti(Strudent stud) {
stud.Godinestudija = 4;
// 2
}
Sta je poenta ovde ? Funkcija PostaviOsnovneVrednosti je void. Ali u posle programske linije //1 pera vec ima poslavljene godine studiranja, jer je funkciji PostaviOsnovneVrednosti poslata referenca na objekat a ne sam objekat. I taj objekat je promenjen.
[ Valerij Zajcev @ 08.07.2007. 19:54 ] @
Code: class Program
{
static void Main(string[] args)
{
Student vlada = new Student(); // vlada je ref i pokazuje na objekat u heapu (Student)
Console.WriteLine(vlada.getGodina); //0
Student.postaviOsnovneVrednosti(vlada); //referenca vlada se prosledjuje metodu
Console.WriteLine(vlada.getGodina); //2
vlada.getGodina = 3;
Console.WriteLine(vlada.getGodina); //3
}
class Student
{
private int godinaStudija;
public int getGodina
{
get { return godinaStudija; }
set { godinaStudija = value;}
}
public static void postaviOsnovneVrednosti(Student std) //vlada je sada std
{
std.godinaStudija = 2; //vlada je na drugoj godini studija
}
}
Sad se vec osecam glupo.
1) Ja sam do sada mislio da je vlada objekat ali ispade da je referenca?
2) u liniji sa funkcijom prosledio sam "vlada" tj "referencu" iz prve linije koja ide tamo i dobija vrednost godine 2 jel to ok?
3) ako je sve u redu to gore cemu onda ona linija sa funkcijom kad svejedno je da li je pozvana funkcija ili jednostavno dodeljena nova godina sa vlada.getGodina = 4;?
[ toxi_programer @ 08.07.2007. 21:07 ] @
Ma vidi, najbolje da gledaš na to ovako: kad napraviš Objekat referentnog tipa, na primer:
Student pera = new Student();
"pera" mi je referenca na mesto gde je smešten novokreirani objekat. Dakle new napravi objekat i snimi ga u memoriju a ti preko "pera" pristupaš tom objektu.
Ovo pod 2 si OK shvatio.
3. Recimo da imaš neku funkciju koja mora da odradi nešto sa npr TextBox kontrolom, dakle kao parametar toj funkciji moraš da proslediš TextBox kontrolu. Ako ta kontrola ima na primer 100 000 znakova, kopiranje bi bilo sporo, pa ti proslediš referencu i ništa se ne kopira i sve radi veoma brzo + moći ćeš da menjaš izgled i sva ostala podešavanja te prosledjene TextBox kontrole. Ovo ima i loših strana, ali to nije tema...
[ Valerij Zajcev @ 08.07.2007. 21:34 ] @
Znaci kada radim sa referencama podatke na koje ukazujem obradjujem u void funkcijama, tj. ne vracam vrednost vec direktno manipulisem podacima te mi se na taj nacin program brze izvrsava.
to je onda ovo:
Code:
int x = 5;
int y = x; // y je sada 5
x++; // nema efekta na y
a kod referenci:
Code:
broj x = new broj();
broj y = x; // y je referenca na referencu(x) na objekat
y.vrednost = 8; // sada je referenca x = 8
Ovo deluje bezveze sada ali kapiram da ce na nekom vecem programu kada treba da se stedi memorija da zatreba. Voleo bih da me neko ispravi ako opet gresim u shvatanju
[ toxi_programer @ 08.07.2007. 21:58 ] @
Dobar si, dobar si
Eh da si se "bahćo" sa C/C++ jezikom sad bi mnogo lakše i "šire" uviđao ove stvari
[ Java Beograd @ 09.07.2007. 10:37 ] @
Pa i grešiš. Nije poenta u štednji memorije. Poenta je da objeka stoji negde u memoriji, i tom objektu pristupaš preko reference. Ako je objekat, na primer neki spsak, ti pozoveš funkciju koja štampa spisak i proslediš joj referencu.
Dakle, nešto kao: "naštampaj spisak, koji ćeš naći preko ove reference ... "
[ toxi_programer @ 09.07.2007. 12:17 ] @
A šta sam ja rekao? :)
Znači prosleđuješ referencu, a ne kopiraš sam objekat. Na taj način se proces ubrzava, zar ne?
[ mmix @ 09.07.2007. 13:39 ] @
Citat: toxi_programer: A šta sam ja rekao? :) Znači prosleđuješ referencu, a ne kopiraš sam objekat. Na taj način se proces ubrzava, zar ne? Pa posto u NETu ne postoji prosledjivanje objekata po vrednosti, taj deo rasprave je besmislen.
@Valerij: stvarno reference nemaju nikakve veze sa stednjom memorije, one su jednostavno instrument koji ti omogucava da pristupis objekatu, kao sto ti toxi i Java objasnise. Vazno je da skontas prirodu te relacije, svaka referenca pokazuje na tacno nula (null) ili jedan objekat u zavisnosti od toga da li je inicijalizovana, dok obrnuto ne vazi, na jedan objekat moze da pokazuje od jedne do "beskonacno" referenci (ako ni jedna referenca vise ne pokazuje na objekat onda je objekat "izgubljen" i bice pociscen od strane GCa).
Jedini (legalni) nacin da u .NETu preneses objekat u neki metod je po referenci, .NET ti ne omogucava da naprvis kopiju objekta i da u metodi radis nad kopijom. Samim tim svaka promena nad objektom unutar funkcije je automatski vildjiva kroz SVE reference koje na taj objekat pokazuju. Da li je to dobro ili lose zavisi iskljucivo od dizajna tvog programa.
Ova varka (da se po defaultu value tipovi prenose po vrednosti a referentni po referenci) je ono sto zbunjuje dosta ljudi, jer se fundamentalno protivi zdravom razumu :)
[ Valerij Zajcev @ 09.07.2007. 15:14 ] @
Znaci sad referenca sluzi da se objekat prenese u metod?
Code: static void Main(string[] args)
{
Broj celobrojan = new Broj(); //celobrojan je referenca na nov objekat
Console.WriteLine(celobrojan.setBroj); //prikazuje broj 0 (automatska dodela)
refBroj.refPromeniBroj(celobrojan); /*pozivam klasu refBroj i njen metod
kome prosledjujem referencu "celobrojan" kao novu referencu Broj parametar u kome menjam broj
sada mi je celobrojan = 8 {OVAJ KORAK JE TAJ KOJI ME ZBUNI}*/
Console.WriteLine(celobrojan.setBroj);
}
class Broj
{
public int setBroj;
}
class refBroj
{
public static void refPromeniBroj(Broj parametar)
{
parametar.setBroj = 8;
}
}
Znaci ja sam mogao da kazem celobrojan.setBroj = 8; ali onda to nije po referenci ali "istu" tu stvar treba da uradim tako sto cu da prosledim objekat nekom metodu i unutar tog metoda da menjam vrednost broja tj. ovog propertija iz klase Broj. Zasto mi je onda trebala ova druga klasa refBroj? I krunisano pitanje zasto sam sve ovo radio kad je moglo celobrojan.setBroj = 8;
Ovaj primer sam malo preradio ali nikako ne shvatam cemu?
[Ovu poruku je menjao Valerij Zajcev dana 09.07.2007. u 16:54 GMT+1]
[ Shadowed @ 09.07.2007. 16:43 ] @
Mah, ne sluzi referenca nicemu. Ili bolje receno sluzi svemu :)
Uvek se to tako radi, imas objekat kreiran u memoriji i reference na njega i ti uvek u kodu pises imena referenci. Nezavisno od toga gde to koristis. To sto se tokom teme navodilo su samo posledice takvog pristupa, ne razlog za njega.
[ Valerij Zajcev @ 09.07.2007. 17:22 ] @
U redu je mislim da sam sam poceo da se snalazim, nego...
1) ako prosledim neki argument metodu a on je value tipa(int i) metod ce da ga recimo inkrementira ali nece promeniti argument vec samo parametar tako da ce mi i u Main() funkciji i dalje biti ona prva vrednost. Sem ako upotrebim (ref int i) cime menjam i parametar i argument, a prazan prosledjujem kroz (out int i)
2) Objekat je "reference type" i kada njega prosledim metodu, i nesto na njemu promenim proemnio sam ono na sta referenca ukazuje, i zato mi ne treba ref ni out, jer objekat mogu i bez vrednosti da prosledim.
Ako nije ovo dobro onda ne znam vise sta je ? :D
[ Shadowed @ 09.07.2007. 18:26 ] @
To je to ;)
[ Valerij Zajcev @ 09.07.2007. 19:29 ] @
Ne ne sad mi je sve jasno samo sam morao da procitam sve o pokazivacima iz Ritchijeve knjizice :) Sve vreme nisam video primenu zasto bih kog djavola radio sve ovo ako moze i na drugi nacin, nesrecom nisam primetio da u primerima nema y = promeniX(x); vec samo promeniX(x);
Svejedno hvala svima :D
[ Java Beograd @ 10.07.2007. 08:50 ] @
Bingo
[ Valerij Zajcev @ 17.09.2007. 20:21 ] @
Reference tipovi (klasa recimo) u metod se prosledjuje po referenci, a ne po vrednosti. Znaci kada objekat ode u metod pokazuje na istu adresu kao i ranije ok. Ali zasto se onda u nekim slucajevima reference tip prosledjuje sa kljucnom reci "ref" ako vec ide u metod kao referenca?
[ android~paranoid @ 17.09.2007. 22:28 ] @
Citat: Valerij Zajcev: Ali zasto se onda u nekim slucajevima reference tip prosledjuje sa kljucnom reci "ref" ako vec ide u metod kao referenca?
http://msdn2.microsoft.com/en-us/library/14akc2c7(VS.71).aspx
Code: // cs_ref.cs
using System;
public class MyClass
{
public static void TestRef(ref char i)
{
// The value of i will be changed in the calling method
i = 'b';
}
public static void TestNoRef(char i)
{
// The value of i will be unchanged in the calling method
i = 'c';
}
// This method passes a variable as a ref parameter; the value of the
// variable is changed after control passes back to this method.
// The same variable is passed as a value parameter; the value of the
// variable is unchanged after control is passed back to this method.
public static void Main()
{
char i = 'a'; // variable must be initialized
TestRef(ref i); // the arg must be passed as ref
Console.WriteLine(i);
TestNoRef(i);
Console.WriteLine(i);
}
}
Output
b
b
Citat: mmix: Pa posto u NETu ne postoji prosledjivanje objekata po vrednosti, taj deo rasprave je besmislen.
Citat: 2.6.1.2 Reference types
If a type consumes significant memory resources, then a reference type provides more benefits over a
value type. Reference types (including objects, interfaces, and pointers) are so called because they
contain references to heap-based objects and can be null. These types are passed by reference,
meaning that when you pass such an object into a function, an address of or pointer to the object is
passed—not a copy of the object, as in the case of a value type. Since you are passing a reference,
the caller will see whatever the called function does to your object. The first benefit here is that a
reference type can be used as an output parameter, but the second benefit is that you don't waste
extra resources because a copy is not made. If your object is large (consuming lots of memory), then
reference types are a better choice.
Zvuci kao da imas izbor, a verovatno nemas :), pod objektom se moze smatrati i value type podataka pa onda u tom slucaju nije veliki za kopiranje.
[ Valerij Zajcev @ 17.09.2007. 23:20 ] @
Code:
static void Main()
{
string myString = "original";
func(ref myString);
string mySecondString = "originalTwo";
funcTwo(mySecondString);
Console.WriteLine();
Bomb myBomb = new Bomb("tomahawk", "SQ101");
bombFunc(ref myBomb);
Console.ReadLine();
}
public static void bombFunc(ref Bomb par)
{
par.air = "airsabre";
par = new Bomb(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<!!!
}
public static void func(ref string par)
{
par = "changed";
}
public static void funcTwo(string par)
{
par = "changedTwo";
}
Citat:
Passing value types by reference--as demonstrated above--is useful, but ref is also useful for passing reference types. This allows called methods to modify the object to which the reference refers because the reference itself is being passed by reference. The following sample shows that when a reference type is passed as a ref parameter, the object itself can be changed.
@android~paranoid hvala na linku pomoglo je kolko tolko. Prvi deo koda tu mi je sve jasno sta se desava ali mene buni samo ova crvena recenica i onaj deo koda kada saljem (MyBomb), a on onda uradi (par = new Bomb();), sta podrazumeva pod tim da je ceo objekat promenjen, jer ocigledno je da ne moram da ga saljem po referenci ako cu samo clanove da menjam, jer to moze i bez toga.
\\edit: kad sam procitao svoj text shvatio sam :)
[Ovu poruku je menjao Valerij Zajcev dana 18.09.2007. u 00:35 GMT+1]
Copyright (C) 2001-2024 by www.elitesecurity.org. All rights reserved.
|