ďťż

Ładny brzuch

const char * napis() { char ile[3] = {'a', 'b', 'c'}; return ile; }

czemu w wywołaniu takiej funkcji w ten sposób:
cout << napis();
wyświetlają się jakieś dziwne znaczki zamiast ciągu "abc" ???



Z bardzo prostej przyczyny. Taka inicjalizacja tworzy tablicę 3 trójelementową, która nie jest de'facto poprawnym c-stringiem. Napis w stylu C musi być zakończony NULL'em. U Ciebie nie jest więc strumień wypisuje znaki jakie znalazł gdzieś w pamięci za Twoim napisem, aż napotka po drodze NULL. I przy okazji... Nie zwraca się z funkcji jej zmiennych lokalnych, ale o tym już pewnie poinformował Ciebie kompilator stosownym warning'iem.
Użytkownik reVis edytował ten post 05 październik 2007, 15:14
const char * napis() { char ile[3] = {'a', 'b', 0}; return ile; }
taka funkcja też nie zwraca poprawnie stringu ;]

a czemu nie zwraca się zmiennych lokalnych ??? To co można zwracać !?
Użytkownik OGGY_Lwiatko_89 edytował ten post 05 październik 2007, 16:23
Nie zwraca się zmiennych lokalnych, ponieważ są one niszczone po zakończeniu funkcji. Zwracać możesz obiekty tymczasowe, wskaźniki albo referencję (ale nie zwracaj ich do zmiennych lokalnych, bo ich wartość po zakończeniu funkcji jest nieokreślona). Jeżeli jednak bardzo chcesz, to możesz zrobić tak:

#include <iostream> using namespace std; const char *napis() { static const char *c = "abc" + '0'; return c; } int main() { cout << napis() << endl; }.
Użytkownik neosnooze edytował ten post 05 październik 2007, 16:45


Nie można zwrócić wskaźnika do zmiennej utworzonej w funkcji! Bo zmienna jest niszczona po funkcji (return).

Ja to rozwiązałem po prostu tak by funkcja zwracała stringa.

#include <string.h>
...
string function()
{

//ewentualnie, bo nie pamiętam: ostatni element, można NULLa dać
return xxx;
}

...
{
f=function.c_str(); //<-- zwraca wskaźnik (const) char*
}
...

PS. char* można zwrócić pod warunkiem, że utworzymy zmienną przez "new".


Nie zwraca się zmiennych lokalnych, ponieważ są one niszczone po zakończeniu funkcji. Zwracać możesz obiekty tymczasowe, wskaźniki albo referencję (ale nie zwracaj ich do zmiennych lokalnych, bo ich wartość po zakończeniu funkcji jest nieokreślona).
no ale gdyby to nie była tablica znaków tylko np typ double to można wysłać ;] pozatym funkcja zwraca wartość a nie zmienną więc wywołanie powyższej funkcji wygląda mniej więcej tak:
1. wywołanie funkcji poprzez np. "cout << napis();"
2. funkcja tworzy sobie lokalnie (czyli gdzieś tam na boku) jakąś zmienną
3. wstawia do zmiennej jakąś wartość
4. zwraca to co w zmiennej (ale tylko wartość)
5. zmienna jest niszczona
6. strumień cout dostał wartość (nie zmienną !) więc ją wyświetla

Ale do c-stringów się to nie sprawdza ponieważ wówczas funkcja zwraca adres do tablicy która po zakończeniu funkcji jest niszczona więc zwraca adres do czegoś co nie istnieje (!) i stąd miałem problemy. dzięki za to słowo "static", rzadko używam c-stringów to zapomniałem o tym :)


...
no wlasnie, dlatego ze zwraca wskaznik to nie ma to sensu. jesli chcesz zrobic cos takiego (tworzyc lokalnie tablice i zwracac na zewnatrz funkcji bez uzycia obiektow) to mozna, ale trzeba stosowac inteligentne wskazniki, shared_array w tym przypadku - dzieki temu tablica zostanie usunieta gdy zakonczone zostana wszystkie jej uzycia, nie wczesniej.

A bez inteligentnych pointerow to sie nie da? :P Wystarczy, ze tablica bedzie alokowana na stercie a nie stosie.


const char *napis() {
static const char *c = "abc" + '0';
return c;
}

O jeez, po
1. nie potrzeba static bo zwracamy wartosc zmiennej c, nie jej adres,
2. "abc" + '0' - no comment


A bez inteligentnych pointerow to sie nie da? :P Wystarczy, ze tablica bedzie alokowana na stercie a nie stosie.
jesli po prostu uzyjesz new to ciekawe gdzie usuniesz ten obiekt? przez koncem maina? :>

To tak, żeby było jasne czemu nie można zwracać zmiennych lokalnych z funkcji. Sam podałeś przykład, że można zwracać tak liczbę double. Owszem można, ale zwracasz już jej kopię która jest gdzie indziej w pamięci. Gdy zwracasz wskaźnik (tak jak u Ciebie) to zwrócisz kopię wskaźnika wskazującego na miejsce w pamięci które już zostało wyczyszczone poprzez wyjście z zakresu funkcji. Czyli dostaniesz wskaźnik na miejsce w pamięci gdzie już nic nie ma.

Reasumując podany wyżej przykład możesz napisać:const char* fun() { const char* a = "abc"; return a; }


jesli po prostu uzyjesz new to ciekawe gdzie usuniesz ten obiekt? przez koncem maina? :>
Ludzie od wiekow tworzyli metody-fabryki uzywajac zwyklych pointerow i jakos zyli.

  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • zsf.htw.pl
  •