[ drugtito @ 08.06.2008. 13:38 ] @
POzdrav svima da li postoji mogucnost da funkcija vrati niz kao: int * Fu() { int x[3] = {11,15,9}; return x; }; Tacnije na koji nacin i kako da iz funkcije vratim niz? pozdrav |
[ drugtito @ 08.06.2008. 13:38 ] @
[ Burgos @ 08.06.2008. 13:50 ] @
Treba da vratiš pokazivač na prvi element, kao i broj elemenata niza. Niz unutar funkcije moraš deklarisati kao statički ili ga kreirati u memoriju operatorom new.
Code: #include <iostream> int* Fu(int *n) { static int x[3] = {11,15,9}; //može i: int x = new int[3]; *n = 3; return x; }; int _tmain(int argc, _TCHAR* argv[]) { int n; int *niz; niz = Fu(&n); for(int i = 0; i < n; i++) std::cout << niz[i] << std::endl; return 0; } Nadam se da ne pišeš višenitnu aplikaciju - static u tom slučaju ume veoma da zagorča život. [ deerbeer @ 08.06.2008. 15:34 ] @
Citat: @Burgos Nadam se da ne pišeš višenitnu aplikaciju - static u tom slučaju ume veoma da zagorča život. @drugtito Ako pises visenitnu aplikaciju ili ako koristis new operator da bi kreirao niz obavezno brisi memoriju koju si alocirao unutar funkcije koja ti vraca niz : Code: int _tmain(int argc, _TCHAR* argv[]) { int n; int *niz; niz = Fu(&n); // kreirao si niz sa int* x = new int[3]; for(int i = 0; i < n; i++) std::cout << niz[i] << std::endl; delete [] niz ; // dodato ... return 0; } U tvom primeru : Code: int * Fu() { int x[3] = {11,15,9}; return x; }; vracas null (prazan) pointer jer niz x je lokalna promenljiva u funkciji i brise se sa stack-a odmah po izlasku iz funkcije [ Goran Arandjelovic @ 08.06.2008. 19:28 ] @
@drugtito
Ili jednostavno ne moraš previše da se mučiš da razmišljaš gde si šta oslobodio.. koristi vector ako ti ne smeta. Ili ako ti smeta, koristi pametne pokazivače kao wrapper oko tog niza..i ne razmišljaš o oslobađanju... [ BinaryRuler @ 08.06.2008. 21:59 ] @
Mislim da ti je naj sigurnije da vratis niz kroz parametar.
Code: void Fu(int *x) { x[0] = 11; x[1] = 15; x[2] = 9; }; int _tmain(int argc, _TCHAR* argv[]) { int n; int niz[3]; Fu(niz); for(int i = 0; i < 3; i++) std::cout << niz[i] << std::endl; system("PAUSE"); return 0; } [ Burgos @ 08.06.2008. 22:12 ] @
Mislim da je ovo mnogo nesigurnije, iz prostog razloga što ne prosleđuješ i broj elemenata niza.
A zašto bi takav pristup bio sigurniji? Ne vidim razliku između kreiranja memorije unutar spoljne i unutrašnje funkcije. Možda je lakši pristup, ne zahteva new i delete operatore, ali uvodi više ograničenja. PS. Moram se osloboditi nekih gadnih navika ;). Prvobitni kod bih napisao ovako: Code: #include <iostream> int* Fu(int &n) { static int x[3] = {11,15,9}; //int *x = new int[3]; //x = {11,15,9}; n = 3; return x; }; int _tmain(int argc, _TCHAR* argv[]) { int n; int *niz; niz = Fu(n); for(int i = 0; i < n; i++) std::cout << niz[i] << std::endl; return 0; } I da dodam, ne vidim prednost korišćenja C nizova, umesto kontejnera vector. Mislim da bi to bilo najbolje. [Ovu poruku je menjao Burgos dana 08.06.2008. u 23:26 GMT+1] [ BinaryRuler @ 08.06.2008. 22:25 ] @
Code: void Fu(int *x, int *n) { x[0] = 11; x[1] = 15; x[2] = 9; *n=3; }; int _tmain(int argc, _TCHAR* argv[]) { int n; int niz[3]; Fu(niz,&n); for(int i = 0; i < 3; i++) std::cout << niz[i] << std::endl; system("PAUSE"); return 0; } Ok evo ispravio sam, mislio sam da se podrazumeva da mora da vrati br elemenata. Ne vidim zasto bi bio ogranicen ovakvim pristupom? [ BinaryRuler @ 08.06.2008. 22:31 ] @
Code: void Fu(int *x, int *n) { delete []x; x = new int [10]; for(int i=0; i<10; i++) x[i]=i+1; *n=10; }; int _tmain(int argc, _TCHAR* argv[]) { int n; int* niz=new int[3]; Fu(niz,&n); for(int i = 0; i < n; i++) std::cout << niz[i] << std::endl; system("PAUSE"); return 0; } Evo primera sa redimenzionisanjem. A kroz parametar je sigurnije zbog one price sa stackom sto je rekao deerbeer. I ako hoces da izbegnes static. [ Burgos @ 08.06.2008. 23:09 ] @
?
Code: #include "stdafx.h" #include <iostream> int* Fu(int *n) { int *x = new int[3]; x[0] = 11; x[1] = 15; x[2] = 9; *n = 3; return x; }; int _tmain(int argc, _TCHAR* argv[]) { int n; int *niz; niz = Fu(&n); for(int i = 0; i < n; i++) std::cout << niz[i] << std::endl; delete []niz; return 0; } Interesuje me šta se dešava sa preostalih 7 članova niza koje si napravio u funkciji, kada se obriše int[3], tj. kada program izađe iz oblasti važenja (dešava se da memorija curi). Evo i napismeno: Code: Detected memory leaks! Dumping objects -> {167} normal block at 0x002281B8, 40 bytes long. Data: < > 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 Object dump complete. Code: #include "stdafx.h" #include <iostream> #include "crtdbg.h" void Fu(int *x, int *n) { delete []x; x = new int [10]; for(int i=0; i<10; i++) x[i]=i+1; *n=10; } int _tmain(int argc, _TCHAR* argv[]) { #ifndef NDEBUG int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); flag |= _CRTDBG_LEAK_CHECK_DF; _CrtSetDbgFlag(flag); #endif #ifdef _DEBUG #define new new(_NORMAL_BLOCK, __FILE__, __LINE__) #endif int n; int* niz=new int[3]; Fu(niz,&n); for(int i = 0; i < n; i++) std::cout << niz[i] << std::endl; system("PAUSE"); return 0; } [ deerbeer @ 08.06.2008. 23:25 ] @
Citat: @SkyDiver Mislim da ti je naj sigurnije da vratis niz kroz parametar. Pitanje je bilo kako funkcija da vrati tj. da kreira niz .... Tvoj primer pokazuje kako popuniti niz u okviru neke funkcije ..a sta ako ne znas unapred koliki ce taj niz biti .. onda bi morao da koristis new operator ili std::vector u samoj funkciji sto je najbolje resenje Citat: @Goran Arandjelovic Ili jednostavno ne moraš previše da se mučiš da razmišljaš gde si šta oslobodio.. koristi vector ako ti ne smeta. Ili ako ti smeta, koristi pametne pokazivače kao wrapper oko tog niza..i ne razmišljaš o oslobađanju... std::vector je ok za primitivne tipove ... ali ako hoce da drzi objekte ili strukture a da nisu pointeri (tj. dinamicki kreirani objekti sa new operatorom) u vector listi morace da napravi copy-construktor za svaku klasu ili strukturu , onda ce svaki clan te vector liste sadrzati kopiju sa stack-a . i ne mora da poziva delete za svaki kao sto je slucaj ako ima pointer na kreirani objekat na heap-u ... Ne znam koliko ima smisla pricati unapred (@drugtito se nije jos ni oglasio povodim prethodnih nasih postova :) ako mu dosad nesto nije bilo jasno ... PS: Drug Tito je rekao : Studenti su u pravu !!!!! - Jubilarna 40 godina od studentskog protesta '68 - http://glassrbije.org/index.ph...iew&id=12516&Itemid=30 [ Goran Arandjelovic @ 08.06.2008. 23:38 ] @
Citat: deerbeer: std::vector je ok za primitivne tipove ... ali ako hoce da drzi objekte ili strukture a da nisu pointeri (tj. dinamicki kreirani objekti sa new operatorom) u vector listi morace da napravi copy-construktor za svaku klasu ili strukturu , onda ce svaki clan te vector liste sadrzati kopiju sa stack-a . i ne mora da poziva delete za svaki kao sto je slucaj ako ima pointer na kreirani objekat na heap-u ... Ne znam koliko ima smisla pricati unapred (@drugtito se nije jos ni oglasio povodim prethodnih nasih postova :) ako mu dosad nesto nije bilo jasno ... :) Heh..da, vidim da se nije oglasio, a mi se raspričali možda malo više, ali kad već jesmo moraću da kažem da nije toliko bitno jesu ili ne primitivni tipovi. 1) Može i sam vektor da drži na heapu i da ima wrapper oko njega (čitaj: neki smart pointer), tako da nebi bilo kopiranja celog vektora. 2) Ili lepo može da implementira Move Constructor u svakom svom tipu i to je to...nema duplog kopiranja objekta, kod return poziva (a kad dođu rvalue reference u novom Std-u, onda nema problema :)) ali ovo je malo previše..:))) skrenuo sam s teme... :) [Ovu poruku je menjao Goran Arandjelovic dana 09.06.2008. u 00:49 GMT+1] [ drugtito @ 09.06.2008. 00:32 ] @
POzdrav
elem Hvala na odgovorima, pomogli ste mi. Nego poEnta je da sam zacrtao da funkcija vrati niz i to ti je :) znam da imam jos drugih resenja, ali.............. srbin je to, inat. Hvala jos jednom svim DRUGOVIMA :) "Drugovi, pred nama su odlučujući dani. Naprijed sada u konačnu pobjedu! Iduću konferenciju moramo održati u oslobođenoj zemlji i od tuđina i od kapitalista!" ??.10.1940 Drug Tito - From Wikipedia [Ovu poruku je menjao drugtito dana 09.06.2008. u 01:42 GMT+1] [Ovu poruku je menjao drugtito dana 09.06.2008. u 01:43 GMT+1] [ BinaryRuler @ 09.06.2008. 07:17 ] @
deerbeer, ja sam redimenzionisao niz u funkciji i to radi odlicno, ti u funkciju uvek mozes da redimenzionises niz na isti nacin.
Code: void Fu(int *x, int *n) { delete []x; x = new int [10]; for(int i=0; i<10; i++) x[i]=i+1; *n=10; }; int _tmain(int argc, _TCHAR* argv[]) { int n; int* niz=new int[3]; Fu(niz,&n); for(int i = 0; i < n; i++) std::cout << niz[i] << std::endl; system("PAUSE"); return 0; } [ deerbeer @ 09.06.2008. 08:54 ] @
Citat: SkyDiverX: deerbeer, ja sam redimenzionisao niz u funkciji i to radi odlicno, ti u funkciju uvek mozes da redimenzionises niz na isti nacin. Izvini moj komentar se odnosio se na drugi primer : Code: void Fu(int *x, int *n) { x[0] = 11; x[1] = 15; x[2] = 9; *n=3; }; int _tmain(int argc, _TCHAR* argv[]) { int n; int niz[3]; Fu(niz,&n); for(int i = 0; i < 3; i++) std::cout << niz[i] << std::endl; system("PAUSE"); return 0; } Ok .. postoje mnogo nacina u C++-u da se ovo uradi ... sve zavisi od afiniteta i znanja onog koji ga implementira... Svaki predlog je u principu dobar i ima svoju primenu ... [ Burgos @ 09.06.2008. 09:36 ] @
Ponovo ti kažem da ovaj kod izaziva memory-leak. Nedostaje ti
Code: pre izlaska iz glavne f-je. delete []niz Čak i u ovom slučaju: Code: void Fu(int *x, int *n) { delete []x; x = new int [2]; for(int i=0; i<2; i++) x[i]=i+1; *n=2; } Dolazi do leak-a. Sve u svemu, jako loš pristup. Treba izbegavati redimenzionisanje niza kreiranog u nekom drugom bloku. [ Goran Arandjelovic @ 09.06.2008. 10:03 ] @
Citat: Burgos: Ponovo ti kažem da ovaj kod izaziva memory-leak. Nedostaje ti Code: pre izlaska iz glavne f-je. delete []niz Čak i u ovom slučaju: Code: void Fu(int *x, int *n) { delete []x; x = new int [2]; for(int i=0; i<2; i++) x[i]=i+1; *n=2; } Dolazi do leak-a. Sve u svemu, jako loš pristup. Treba izbegavati redimenzionisanje niza kreiranog u nekom drugom bloku. Heh...tek ovo što si napisao ne smeš da radiš... Code: void Fu(int *x, int *n) { delete []x; // otkud znas da je ovaj niz na heapu, a ne na stacku?! x = new int [2]; for(int i=0; i<2; i++) x[i]=i+1; *n=2; } Prvo bi trebalo da ispitaš da li je određeni niz (ako je prosleđen pokazivač na njega) na heapu ili na stacku. Ovo je, generalno, nemoguće portabilno uraditi...ali je moguće sledeće (uz uslov da se zna da niz sigurno nije static) Code: int na_heapu(void *p) { char c; // sada znamo da je ovaj jedan bajt na vrhu steka if((int)p < (int)&c){ //p pokazuje na heap (ili mozda static?, ali smo izuzeli taj slucaj) return(1); }else{ //p pokazuje na stack return(0); } } Ovo je "prljavo", tako da ne preporučujem...ali može da prođe ok. Sasvim je bezbedno uraditi ovo... što će dobro raditi ako je niz na stacku ili na heapu... Code: void Fu(int *x, int *n, int maxelem) { // ovde maxelem oznacava da je maksimalan broj elemenata 3, // jer inace tu informaciju nismo imali... x[0] = 11; x[1] = 15; x[2] = 9; *n=3; // i ova izmena elemenata jeste sasvim bezbedna // i ova funckija nebi trebalo da ima odgovornost za brisanje niza ni u kom slucaju... }; [ Burgos @ 09.06.2008. 10:42 ] @
Ne radim to ja, pokazivao sam SkyDiverXu da je to jedan užasan i krajnje opasna tehnika - redimenzionisanje niza, odn. petljanje sa memorijom nastalom na nekom drugom mestu.
Citat: Goran Arandjelovic: Prvo bi trebalo da ispitaš da li je određeni niz (ako je prosleđen pokazivač na njega) na heapu ili na stacku. Ovo je, generalno, nemoguće portabilno uraditi...ali je moguće sledeće (uz uslov da se zna da niz sigurno nije static) Reference: Art Of Programming: "Kako utvrditi da li dati pokazivac pokazuje na dinamicki alocirani objekat." ;) Citat: Goran Arandjelovic: Sasvim je bezbedno uraditi ovo... što će dobro raditi ako je niz na stacku ili na heapu... Code: void Fu(int *x, int *n, int maxelem) { // ovde maxelem oznacava da je maksimalan broj elemenata 3, // jer inace tu informaciju nismo imali... x[0] = 11; x[1] = 15; x[2] = 9; *n=3; // i ova izmena elemenata jeste sasvim bezbedna // i ova funckija nebi trebalo da ima odgovornost za brisanje niza ni u kom slucaju... }; Da, sasvim je bezbedna, jer se ne petlja sa memorijom. SkyDividerX je naveo primer kako redimenzionisati prosleđen niz, a ja sam samo rekao kako je to nebezbedna taktika, što si i ti pokazao navedenim primerima. [ Burgos @ 09.06.2008. 10:44 ] @
Citat: Goran Arandjelovic: Heh...tek ovo što si napisao ne smeš da radiš... Code: void Fu(int *x, int *n) { delete []x; // otkud znas da je ovaj niz na heapu, a ne na stacku?! Ne znam, zato sam i rekao da je opasno. Pored problema nastalih curenjem memorije, moguće su i dalje komplikacije. Nije to moj kod: Citat: SkyDiverX: Code: void Fu(int *x, int *n) { delete []x; x = new int [10]; for(int i=0; i<10; i++) x[i]=i+1; *n=10; } [ Goran Arandjelovic @ 09.06.2008. 11:49 ] @
@Burgos
Izvini, nisam video da nije tvoj kod... :) -- Mislim da nije samo Art of Programming...ne znam odakle mi to tacno. :) Edit: @Burgos Sad vidim tvoj potpis... Linus bi me verovatno iskritikovao za ovo oko portabilnosti... :)) [ Burgos @ 09.06.2008. 11:59 ] @
Nema problema :).
A za Linusa - ko ga šiša ;). [ BinaryRuler @ 09.06.2008. 17:32 ] @
Burgos kada bi uradio delete [] niz; na kraju funkcije opet bi vratio NULL kroz parametar, ne zaboravi da se vraca samo pokazivac.
Goran Arandjelovic naravno da mora da bude na heap-u da bi prosao delete u prvoj liniji funkcije. Code: void Fu(int *x, int *n) { delete []x; x = new int [10]; for(int i=0; i<10; i++) x[i]=i+1; *n=10; }; int _tmain(int argc, _TCHAR* argv[]) { int n; int* niz=new int[3]; Fu(niz,&n); for(int i = 0; i < n; i++) std::cout << niz[i] << std::endl; delete[] niz; //recimo odavde mi vise nece trebati niz pa sam ga delet-ovao. system("PAUSE"); return 0; } Da ne bi bilio leak-a kada se zavrsi koriscenje niz-a uradi se delete[] niz; kao sto sam naveo u kodu, i vise nema memory leak-a, bar ja nisam imao problema sa ovim. Ako postoji neko sigurnije resenje za ovaj problem dajte ga da zamenim ovo nesigurno resenje. Sto ste napali moje resenje ;), nego, ako postoji drugo resenje zanima me. [Ovu poruku je menjao SkyDiverX dana 09.06.2008. u 18:55 GMT+1] [ Burgos @ 09.06.2008. 18:20 ] @
.
Citat: SkyDiverX: Burgos kada bi uradio delete [] niz; na kraju funkcije opet bi vratio NULL kroz parametar, ne zaboravi da se vraca samo pokazivac. ... Da ne bi bilio leak-a kada se zavrsi koriscenje niz-a uradi se delete[] niz; kao sto sam naveo u kodu, i vise nema memory leak-a, Čekaj, a sta sam tačno rekao? Citat: Burgos: Ponovo ti kažem da ovaj kod izaziva memory-leak. Nedostaje ti Code: pre izlaska iz glavne f-je. delete []niz Ponavljaš se, druže. I šta da ti je ta funkcija u nekoj biblioteci? Lako je ovako videti da ne radi ako se radi sa memorijom u steku. Nijedno od ovih rešenja nije 100% sigurno, treba koristiti delete[] operator. Najsigurnije je koristiti stacic, ali samo ukoliko se radi o single-threaded aplikaciji Citat: Ako postoji neko sigurnije resenje za ovaj problem dajte ga da zamenim ovo nesigurno resenje. Ti si rekao da je tvoje rešenje najsigurnije, samo me interesuje kako si to zaključio. I pritom zaboravio da dealociraš memoriju. Ali stvarno, zašto je najsigurnije, interesuje me? [ Goran Arandjelovic @ 09.06.2008. 18:23 ] @
@Burgos
Sada je u poslednjem primeru dealocirao niz... @Sky Ma ok je sasvim :) Ne znam koliko ti je kompleksan kod, jer ovo je samo primer... Samo vodi računa da se taj niz ne "prošeta" kroz desetak f-ja..objekata..itd, a da na kraju izgubiš iz vida ko je odgovoran za njegovo brisanje (kada najčešće dolazi do prevremenog brisanja i dereferenciranja dealociranog prostora). Od toga može vrlo često da boli glava...te je neka opšta preporuka da koristiš pametne pokazivače i STL, sem ako nemaš neke specifične potrebe. [ NastyBoy @ 09.06.2008. 18:49 ] @
Ali chovek je trazhio da mu funkcija vrati novi niz...
[ BinaryRuler @ 09.06.2008. 19:27 ] @
Ovo sam napravio kada sam imao problem oko citanja sa Com porta. Zadatak je bio da moram sve da procitam sa Com porta u jednom cugu. Uredjaj na portu u normalnom rezimu rada nije slao vise od 255 bajtova, ali postojale su situacije (usled nekog kvara softverskog ili hardverskog) da prebaci taj opseg i nikada ne znas koliki ce biti.
Pa sam to resio tako sto da funkciju koja cita sa Com porta, napravio tako da moze da dealocira niz na principu koji sam napisao. I to je radilo ok. Kao sto NastyBoy rece:"Ali chovek je trazhio da mu funkcija vrati novi niz...". Mozemo coveka da uplasimo ovakvim raspravama :), mada meni licno se svidja volim da cujem i druga misljenja. [ Burgos @ 09.06.2008. 19:32 ] @
@Goran,
obrisao je niz u poslednjem primeru, ali uz komentar: Citat: Burgos kada bi uradio delete [] niz; na kraju funkcije opet bi vratio NULL kroz parametar, ne zaboravi da se vraca samo pokazivac. Kao da sam ja predlagao brisanje niza pre izlaska iz funkcije. Nit sam slep, niti glup :). Citat: Goran Arandjelovic: Samo vodi računa da se taj niz ne "prošeta" kroz desetak f-ja..objekata..itd, a da na kraju izgubiš iz vida ko je odgovoran za njegovo brisanje Tačno tako. [ BinaryRuler @ 09.06.2008. 19:44 ] @
Burgos nemoj da se ljutis
![]() Nismo se razumeli, To sto u predhodnim primerima nisam stavljao delete[] nisam ga zaboravio nego me je mrzelo da stavljam jer sam mislio da se podrazumeva. Ispala frka oko delete[] oeratora. Ako ima neko neko drugo resenje za ono sto sam naveo u predhodnom postu neka napise osim da deklarise ultra veliki niz ![]() [Ovu poruku je menjao SkyDiverX dana 09.06.2008. u 21:37 GMT+1] [ Burgos @ 09.06.2008. 21:01 ] @
Ne ljutim se. Možda sam zadrt ali se ne ljutim ;).
[ BinaryRuler @ 09.06.2008. 21:57 ] @
Burgos mogli bi za dane piva malo ozbiljnije da porazgovaramo o ovoj temi uz "ladno pivo"
![]() [ NastyBoy @ 09.06.2008. 22:33 ] @
Niste vi razumeli ni shta sam ja hteo da kazhem ni zashto je inicijalno pitanje vishe na mestu nego ikada pre
[ Eurora3D Team @ 09.06.2008. 23:15 ] @
Ljudi dokle cete da raspravljate o tome kako da fn vrati pointer na niz :)
@deerbeer @SkyDiverX postavio sam kod na ovoj drugoj temi ... http://www.elitesecurity.org/p1970403 [ Burgos @ 10.06.2008. 00:12 ] @
@NastyBoy, pa šta fali mom prvom primeru?
@SkyDividerX, vidimo se, moj si gost :). [ BinaryRuler @ 10.06.2008. 07:09 ] @
Dogovoreno
![]() Nego imam ja jos jedno vrlo interesantno pitanje kada smo vec tu kod funkcija koje vracaju niz. Kako vratiti niz iz funkcije koja se nalazi u dll-u ![]() Copyright (C) 2001-2025 by www.elitesecurity.org. All rights reserved.
|