Pages

vendredi 23 décembre 2011

int[2] comment_retourner_un_tableau();

Vous est-il déjà arrivé de vouloir retourner un tableau de n valeur ?
Un prototype du genre int[2] f(); ?
Et là, c'est le drame, un expected unqualified-id before ‘[’ token empêche de compiler.

La meilleure solution est de retourner un objet. Le plus simple étant std::array du C++0x ou boost::array. Un std::vector fera aussi l'affaire ;).

Une autre solution est de retourner un pointeur. Niveau typage c'est pas le top : on perd l'information sur la taille. Mais pourquoi pas.
Attention quand même ! Regardez bien l'exemple suivant :
int* f()
{
 int a[] = {0,1,2,3,4};
 return a;
}

int main()
{
 int* a = f();
 std::cout << a[2] << ',';
 a[2] = 0;
 int* a2 = new int[5];
 std::cout << a[2] << std::endl;
 return 0;
}
À première vue, rien de bien dangereux. Cependant le compilo nous dit warning: address of local variable ‘a’ returned. Étrange erreur, c'est pourtant ce que l'on veut…
En exécutant le binaire celui-ci affiche quelque chose comme : 3,12812616681
Pourquoi ? Tout simplement parce que 'a' pointe sur une mémoire non allouée, ou pour être plus précis dés-allouée. Bah oui, 'a' en sortant de la fonction f est détruit, mais cela n'empêche pas de retourner son pointeur… vers un espace mémoire libre. Le compilateur nous avait prévenu ;).

En réalité f devrait ressembler à
int* f()
{
 int* a = new int[5];
 a[0] = 0;
 a[1] = 1;
 a[2] = 2;
 a[3] = 3;
 a[4] = 4;
 return a;
}
Mais pour éviter les fuites mémoires, ne pas oublier delete[]. Si on veut retourner un pointeur il sera peut-être préférable de retourner un pointeur intelligent, au moins le delete sera automatique.
On revient à la phrase du début, le plus simple reste le retour d'un objet.

std::array<5, int> f()
{
 return {{0,1,2,3,4}};
}

Aucun commentaire: