J'ai un tableau int arr[5]
qui est passé à une fonction fillarr(int arr[])
:
int fillarr(int arr[])
{
for(...);
return arr;
}
- Comment puis-je retourner ce tableau?
- Comment vais-je l'utiliser, disons que j'ai renvoyé un pointeur comment vais-je y accéder?
std::vector
.5
signature de la fonction est ignorée par le compilateur.Réponses:
Dans ce cas, votre variable de tableau
arr
peut également être traitée comme un pointeur vers le début du bloc de votre tableau en mémoire, par une conversion implicite. Cette syntaxe que vous utilisez:C'est une sorte de sucre syntaxique. Vous pouvez vraiment le remplacer par ceci et cela fonctionnerait toujours:
Donc, dans le même sens, ce que vous voulez retourner de votre fonction est en fait un pointeur vers le premier élément du tableau:
Et vous pourrez toujours l'utiliser comme vous le feriez avec un tableau normal:
la source
array
et&array
sont interchangeables dans de nombreux cas.a
entréeint a[10]
estint[10]
. Ce que vous pouvez dire, c'est que les tableaux se désintègrent en pointeurs vers leur premier élément. (Il s'agit d'une conversion implicite de tableau en pointeur.) Alors votre réponse irait dans le sens du mien. Si vous modifiez votre réponse pour différencier les tableaux, la conversion de tableau en pointeur et les pointeurs, je supprimerai ma réponse car ils auraient les mêmes informations de base et vous étiez le premier.Les fonctions C ++ ne peuvent pas renvoyer de tableaux de style C par valeur. Le plus proche est de retourner un pointeur. De plus, un type de tableau dans la liste d'arguments est simplement converti en pointeur.
Vous pouvez l'améliorer en utilisant un tableau de références pour l'argument et le retour, ce qui empêche la désintégration:
Avec Boost ou C ++ 11, le passage par référence est uniquement facultatif et la syntaxe est moins époustouflante:
Le
array
modèle génère simplement unstruct
contenant un tableau de style C, vous pouvez donc appliquer une sémantique orientée objet tout en conservant la simplicité d'origine du tableau.la source
typedef int array[5]; array& foo();
Mais vous ne même pas besoin de l'typedef si vous soin d'écrire ceci:int (&foo())[5] { static int a[5] = {}; return a; }
l'exemple dans la question serait:int (&foo( int (&a)[5] ))[5] { return a; }
. C'est simple, non?error: function returning array is not allowed
qui se produit si vous omettez les parens externes dans la syntaxe non typedef. Heureusement, aujourd'hui, j'ai revu la règle droite-gauche pour une autre question et j'ai réussi à construire la bonne chose… après vous avoir vu dire que c'était possible… avant de voir que vous avez donné le code: vP.En C ++ 11, vous pouvez revenir
std::array
.la source
(...) you can consider the array returned arr2, totally another array (...)
8,3,5 $ / 8 états-
"Les fonctions ne doivent pas avoir un type de retour de type tableau ou fonction, bien qu'elles puissent avoir un type de retour pointeur de type ou une référence à de telles choses. Il ne doit pas y avoir de tableaux de fonctions, bien qu'il puisse y avoir des tableaux de pointeurs vers des fonctions."
la source
int
, pas un tableau.la réponse peut dépendre un peu de la façon dont vous prévoyez d'utiliser cette fonction. Pour la réponse la plus simple, décidons qu'au lieu d'un tableau, ce que vous voulez vraiment, c'est un vecteur. Les vecteurs sont agréables parce que le look du monde entier comme des valeurs ordinaires ennuyeuses que vous pouvez stocker dans des pointeurs réguliers. Nous examinerons d'autres options et pourquoi vous les souhaitez par la suite:
Cela fera exactement ce que vous attendez de lui. L'avantage, c'est que l'on
std::vector
s'assure que tout est géré proprement. l'inconvénient est que cela copie une très grande quantité de données, si votre baie est grande. En fait, il copie deux fois chaque élément du tableau. il copie d'abord le vecteur pour que la fonction puisse l'utiliser comme paramètre. puis il le copie à nouveau pour le renvoyer à l'appelant. Si vous pouvez gérer vous-même le vecteur, vous pouvez faire les choses un peu plus facilement. (il peut le copier une troisième fois si l'appelant a besoin de le stocker dans une variable quelconque pour faire plus de calcul)On dirait que ce que vous essayez vraiment de faire est simplement de remplir une collection. si vous n'avez pas de raison spécifique de renvoyer une nouvelle instance d'une collection, alors ne le faites pas. on peut le faire comme ça
de cette façon, vous obtenez une référence au tableau passé à la fonction, pas une copie privée de celui-ci. toutes les modifications que vous apportez au paramètre sont visibles par l'appelant. Vous pouvez y renvoyer une référence si vous le souhaitez, mais ce n'est pas vraiment une bonne idée, car cela implique en quelque sorte que vous obtenez quelque chose de différent de ce que vous avez réussi.
Si vous avez vraiment besoin d'une nouvelle instance de la collection, mais que vous souhaitez éviter de l'avoir sur la pile (et toutes les copies qui en découlent), vous devez créer une sorte de contrat pour la gestion de cette instance. la façon la plus simple de le faire est d'utiliser un pointeur intelligent, qui conserve l'instance référencée aussi longtemps que quelqu'un s'y accroche. Il disparaît proprement s'il sort du cadre. Cela ressemblerait à ceci.
Pour la plupart, l'utilisation des
*myArr
œuvres est identique à celle d'un vecteur vanille ordinaire. Cet exemple modifie également la liste des paramètres en ajoutant leconst
mot clé. Maintenant, vous obtenez une référence sans la copier, mais vous ne pouvez pas la modifier, donc l'appelant sait que ce sera la même qu'avant que la fonction n'y arrive.Tout cela est énorme, mais le c ++ idiomatique fonctionne rarement avec les collections dans leur ensemble. Plus normalement, vous utiliserez des itérateurs sur ces collections. qui ressemblerait à quelque chose de plus comme ça
L'utiliser semble un peu étrange si vous n'êtes pas habitué à voir ce style.
foo pointe maintenant vers le début de la modification
arr
.Ce qui est vraiment bien, c'est qu'il fonctionne aussi bien sur des vecteurs que sur des tableaux C simples et de nombreux autres types de collection, par exemple
Ce qui ressemble maintenant beaucoup aux exemples de pointeurs simples donnés ailleurs dans cette question.
la source
&
symbole doit apparaître après le type:void fillarr(std::vector<int> & arr)
Ce:
est en fait traité de la même manière que:
Maintenant, si vous voulez vraiment retourner un tableau, vous pouvez changer cette ligne en
Ce n'est pas vraiment retourner un tableau. vous renvoyez un pointeur au début de l'adresse du tableau.
Mais souvenez-vous que lorsque vous passez dans le tableau, vous ne passez qu'un pointeur. Ainsi, lorsque vous modifiez les données du tableau, vous modifiez en fait les données vers lesquelles le pointeur pointe. Par conséquent, avant de passer dans le tableau, vous devez vous rendre compte que vous avez déjà à l'extérieur le résultat modifié.
par exemple
Je suggère que vous souhaitiez peut-être envisager de mettre une longueur dans votre fonction fillarr comme ceci.
De cette façon, vous pouvez utiliser la longueur pour remplir le tableau à sa longueur, quelle qu'elle soit.
Pour l'utiliser correctement. Faites quelque chose comme ça:
Si tout ce que vous voulez faire est de définir le tableau sur des valeurs par défaut, envisagez d'utiliser la fonction memset intégrée.
quelque chose comme: memset ((int *) & arr, 5, sizeof (int));
Pendant que je suis sur le sujet. Vous dites que vous utilisez C ++. Jetez un œil à l'utilisation des vecteurs stl. Votre code est susceptible d'être plus robuste.
Il existe de nombreux tutoriels. En voici une qui vous donne une idée de la façon de les utiliser. http://www.yolinux.com/TUTORIALS/LinuxTutorialC++STL.html
la source
std::copy
plusmemset
, c'est plus sûr et plus facile. (Et tout aussi rapide sinon plus rapide.)pour renvoyer un tableau à partir d'une fonction, définissons ce tableau dans une structure; Donc ça ressemble à ça
Créons maintenant des variables de la structure de type.
Nous pouvons passer un tableau à une fonction de la manière suivante et lui attribuer une valeur:
Nous pouvons également retourner le tableau. Pour renvoyer le tableau, le type de retour de la fonction doit être de type structure c'est-à-dire marques. C'est parce qu'en réalité, nous passons la structure qui contient le tableau. Le code final peut donc ressembler à ceci.
la source
C'est une question assez ancienne, mais je vais mettre mes 2 cents car il y a beaucoup de réponses, mais aucune ne montre toutes les méthodes possibles de manière claire et concise (je ne suis pas sûr du bit concis, car cela a eu un peu de main. TL; DR 😉).
Je suppose que l'OP voulait retourner le tableau qui a été transmis sans copier comme moyen de le transmettre directement à l'appelant pour le passer à une autre fonction pour rendre le code plus joli.
Cependant, utiliser un tableau comme celui-ci, c'est le laisser se désintégrer en un pointeur et demander au compilateur de le traiter comme un tableau. Cela peut entraîner des bogues subtils si vous passez dans un tableau similaire, la fonction s'attendant à ce qu'il contienne 5 éléments, mais votre appelant passe en fait un autre nombre.
Il existe plusieurs façons de mieux gérer cela. Passez un
std::vector
oustd::array
(je ne sais pas sistd::array
c'était en 2010 lorsque la question a été posée). Vous pouvez ensuite passer l'objet comme référence sans copier / déplacer l'objet.Cependant, si vous insistez pour jouer avec les tableaux C, utilisez un modèle qui conservera les informations sur le nombre d'éléments dans le tableau.
Sauf que ça a l'air moche et super difficile à lire. J'utilise maintenant quelque chose pour aider avec ce qui n'existait pas en 2010, que j'utilise également pour les pointeurs de fonction:
Cela déplace le type là où on pourrait s'y attendre, ce qui le rend beaucoup plus lisible. Bien sûr, l'utilisation d'un modèle est superflue si vous n'utilisez que 5 éléments, vous pouvez donc bien sûr le coder en dur:
Comme je l'ai dit, mon
type_t<>
truc n'aurait pas fonctionné au moment où cette question a été posée. Le mieux que vous auriez pu espérer à l'époque était d'utiliser un type dans une structure:Ce qui recommence à être assez moche, mais au moins est encore plus lisible, bien que cela
typename
puisse être facultatif à l'époque en fonction du compilateur, ce qui se traduit par:Et puis bien sûr, vous auriez pu spécifier un type spécifique, plutôt que d'utiliser mon aide.
À l' époque, les fonctions libres
std::begin()
etstd::end()
n'existait pas, mais auraient pu être facilement mis en œuvre. Cela aurait permis d'itérer sur le tableau d'une manière plus sûre car ils ont du sens sur un tableau C, mais pas un pointeur.En ce qui concerne l'accès au tableau, vous pouvez soit le passer à une autre fonction qui prend le même type de paramètre, soit lui créer un alias (ce qui n'aurait pas beaucoup de sens car vous avez déjà l'original dans cette étendue). Accéder à une référence de tableau revient à accéder au tableau d'origine.
ou
Pour résumer, il est préférable de ne pas autoriser une désintégration de tableau dans un pointeur si vous avez l'intention de le parcourir. C'est juste une mauvaise idée car cela empêche le compilateur de vous protéger de vous tirer dans le pied et rend votre code plus difficile à lire. Essayez toujours d'aider le compilateur à vous aider en conservant les types aussi longtemps que possible, sauf si vous avez une très bonne raison de ne pas le faire.
Éditer
Oh, et pour être complet, vous pouvez lui permettre de se dégrader en un pointeur, mais cela dissocie le tableau du nombre d'éléments qu'il contient. Cela se fait beaucoup en C / C ++ et est généralement atténué en passant le nombre d'éléments dans le tableau. Cependant, le compilateur ne peut pas vous aider si vous faites une erreur et passez la mauvaise valeur au nombre d'éléments.
Au lieu de passer la taille, vous pouvez passer le pointeur de fin, qui pointera vers un après la fin de votre tableau. Ceci est utile car il permet d'obtenir quelque chose qui est plus proche des algorithmes std, qui prennent un pointeur de début et de fin, mais ce que vous retournez n'est maintenant que quelque chose dont vous devez vous souvenir.
Alternativement, vous pouvez documenter que cette fonction ne prendra que 5 éléments et espérer que l'utilisateur de votre fonction ne fera rien de stupide.
Notez que la valeur de retour a perdu son type d'origine et est dégradée en un pointeur. Pour cette raison, vous êtes maintenant seul pour vous assurer que vous n'allez pas dépasser la baie.
Vous pouvez passer un
std::pair<int*, int*>
, que vous pouvez utiliser pour commencer et terminer et le faire circuler, mais cela cesse vraiment de ressembler à un tableau.ou
Assez drôle, c'est très similaire à la façon dont
std::initializer_list
fonctionnent (c ++ 11), mais ils ne fonctionnent pas dans ce contexte.la source
la façon la plus simple de le faire est de le renvoyer par référence, même si vous n'écrivez pas le symbole «&», il est automatiquement renvoyé par référence
la source
Vous pouvez toujours utiliser le résultat comme
la source
Comme indiqué ci-dessus, les chemins sont corrects. Mais je pense que si nous renvoyons simplement une variable de tableau local d'une fonction, elle renvoie parfois des valeurs de déchets en tant qu'éléments.
afin d'éviter que je devais créer le tableau dynamiquement et continuer. C'est quelque chose comme ça.
la source
la source
Source: https://www.tutorialspoint.com/cplusplus/cpp_return_arrays_from_functions.htm
C ++ ne permet pas de renvoyer un tableau entier comme argument à une fonction. Cependant, vous pouvez renvoyer un pointeur vers un tableau en spécifiant le nom du tableau sans index.
En appliquant ces règles sur la question actuelle, nous pouvons écrire le programme comme suit:
La sortie sera:
la source
et à propos de:
la source
En fait, lorsque vous passez un tableau à l'intérieur d'une fonction, le pointeur vers le tableau d'origine est passé dans le paramètre de fonction et donc les modifications apportées au tableau à l'intérieur de cette fonction sont réellement effectuées sur le tableau d'origine.
Exécutez-le et vous verrez les changements
la source
y
elle-même est passée comme une copie d'elle-même, mais comme il s'agit d'un pointeur, vous allez directement opérer sur le tableau. Veuillez modifier votre réponse.Voici un exemple complet de ce type de problème à résoudre
la source
Définissez simplement un type [] comme valeur de retour, comme:
. . . appel de fonction:
la source