PDA

View Full Version : [C++] std::list passaggio parametri ad una funzione


bulmachan
22-08-2008, 22:23
Ho la necessità di passare ad una funzione una std:list, tale funzione ne modificherà il contenuto (in pratica legge dei dati da file e li inserisce in lista con delle push_back), al di fuori di quella funzione deve essere possibile ciclare sulla lista e vederne il contenuto. Essendo abituata a programmare in C mi verrebbe da creare un puntatore e passare quello alla funzione, poi in essa fare via via i miei inserimenti nella mia lista (usando una struct campo intero e next e modificando opportunamenteil campo next). Pensavo usando std::list di potermelo risparmiare e che questo potesse funzionare, dove sbaglio?

readFile(list <int> L) {
...
L.push_back(someInt);
}

void main (void) {
list<int> L;
readFile(L);
for(list<int>::iterator ai=L.begin(); ai!=L.end(); ++ai)
cout << *ai << endl;
}

Scusate eventuali eresie e grazie in anticipo :D

DanieleC88
23-08-2008, 09:27
Se hai programmato in C saprai che i parametri vengono passati per copia alle funzioni chiamate: ebbene, il C++ ti permette di evitare i puntatori passando i parametri per riferimento, se esplicitamente dichiarato. Ti basta aggiungere una & alla dichiarazione di prima per poterla usare come fosse una variabile locale e propagarne le modifiche anche alla funzione chiamante:
void readFile(list<int> &L)
{
/* ... */
L.push_back(someInt);
}

Nota che ho messo anche un void come tipo di ritorno della funzione: anche se non restituisce niente, devi comunque darle un tipo per i valori di ritorno (nonostante il tipo in questione sia "vuoto"). Che io sappia, le uniche funzioni dove è consentito omettere un tipo sono i costruttori.

Noixe
23-08-2008, 11:17
In alternativa puoi continuare a passare il valore per copia e ritornare la lista stessa:


#include <iostream>
#include <list>

std::list<int> readFile(std::list<int> L) {
for (int i = 0; i < 10; i++)
L.push_back(i + 1);
return L;
};

int main () {
std::list<int> L;
L = readFile(L);
for(std::list<int>::iterator ai = L.begin(); ai != L.end(); ai++)
std::cout << *ai << std::endl;

return 0;
}

Anche il main usa int come valore di ritorno e in C++ non si usa void per indicare che la funzione non prende argomenti ma piuttosto non va messo nulla.

Ciao

DanieleC88
23-08-2008, 11:36
in C++ non si usa void per indicare che la funzione non prende argomenti ma piuttosto non va messo nulla.
È identico, anche se effettivamente brutto. :D

Per una funzione dove ci si aspetta che venga modificato qualcosa è meglio passare direttamente il riferimento, altrimenti devono essere effettuate due copie quando si potrebbero benissimo evitare.

ciao ;)

Noixe
23-08-2008, 13:20
Be si era un discorso piu' generale, nel caso in cui non si volesse fare uso di riferimenti o puntatori.

bulmachan
25-08-2008, 22:44
Grazie 1000, si avevo omesso il void per brevità, in realtà la funzione è più complessa e già di suo ritorna un valore (sostanzialmente se la lettura da file è andata a buon fine e se ha riempito correttamente la lista), il dubbio che avevo, non avendo mai usato list, è se fosse in modo "implicito" un puntatore, quindi è sufficiente aggiungere una & alla dichiarazione per passare i parametri come riferimento, e richiamare la funzione così?

void readFile(list<int> &L) {
/* ... */
L.push_back(someInt);
}
int main () {
ist<int> L;
L = readFile(L);
for(list<int>::iterator ai = L.begin(); ai != L.end(); ai++)
cout << *ai << endl;
return 0;
}

Tnk

DanieleC88
26-08-2008, 00:57
è se fosse in modo "implicito" un puntatore, quindi è sufficiente aggiungere una & alla dichiarazione per passare i parametri come riferimento, e richiamare la funzione così?
Uhm, sì, diciamo che è "implicitamente un puntatore", ti basti sapere che puoi utilizzarlo così com'è per propagare le modifiche anche all'esterno della funzione e non lavorare sulle copie. ;)

Albi89
26-08-2008, 02:11
Per altro uno dei primi "tricks" per rendere il codice STL più scattante è proprio quello di non farlo ritornare dalla funzione ma di lavorare sul parametro passato per riferimento: in questo modo si risparmiano almeno due copie (quella per passaggio del parametro e quella necessaria per il return).
Mica male :sofico:

DanieleC88
26-08-2008, 05:43
Capito, non sono stato l'unico a tornare ubriaco ieri notte... :asd:
Per una funzione dove ci si aspetta che venga modificato qualcosa è meglio passare direttamente il riferimento, altrimenti devono essere effettuate due copie quando si potrebbero benissimo evitare.
:p

Scherzo, Albi89... ciao ;)

Albi89
26-08-2008, 10:16
Capito, non sono stato l'unico a tornare ubriaco ieri notte... :asd:

:p

Scherzo, Albi89... ciao ;)

Porc... ammetto di aver letto solo primo e ultimo post :D
Non ero ubriaco ma avevo festeggiato il ritorno alla civiltà... con risultati visibili :sofico: