Retourner un tableau dans une fonction

212

J'ai un tableau int arr[5]qui est passé à une fonction fillarr(int arr[]):

int fillarr(int arr[])
{
    for(...);
    return arr;
}
  1. Comment puis-je retourner ce tableau?
  2. Comment vais-je l'utiliser, disons que j'ai renvoyé un pointeur comment vais-je y accéder?
Ismail Marmoush
la source
46
à strictement parler, dans ce contexte, vous n'avez pas besoin de renvoyer le tableau car le tableau est passé par référence, de sorte que toute modification apportée aux éléments à l'intérieur de 'arr' sera vue en dehors de la fonction.
BuggerMe
12
le retour du tableau est pratique pour chaîner des fonctions.
seand
5
Tant que vous ne commettez pas l'erreur de créer un tableau sur la pile et de lui renvoyer un pointeur.
detly
2
@ismail: il ne peut pas retourner un nouveau tableau, sauf si ce tableau a été alloué dynamiquement. Et si c'est le cas, utilisez std::vector.
GManNickG
4
@BuggerMe: Les tableaux ne sont pas passés par référence (sauf si vous le demandez avec une syntaxe beaucoup plus drôle), dans le code, le tableau se désintègre en un pointeur vers le premier élément et qui est passé à la fonction. La 5signature de la fonction est ignorée par le compilateur.
David Rodríguez - dribeas

Réponses:

204

Dans ce cas, votre variable de tableau arrpeut é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:

int fillarr(int arr[])

C'est une sorte de sucre syntaxique. Vous pouvez vraiment le remplacer par ceci et cela fonctionnerait toujours:

int fillarr(int* arr)

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:

int* fillarr(int arr[])

Et vous pourrez toujours l'utiliser comme vous le feriez avec un tableau normal:

int main()
{
  int y[10];
  int *a = fillarr(y);
  cout << a[0] << endl;
}
Brent écrit le code
la source
45
Pour clarifier, cette "instruction C ++ classique" est fausse; les tableaux ne sont pas des pointeurs.
GManNickG
25
rappelez-vous la règle a [i] == * (a + i)
seand
8
@Brent Nash, non. un tableau est un tableau. Un pointeur vers le début du tableau est un pointeur. Il se trouve que le compilateur a du sucre syntaxique qui fait la traduction pour vous dans certaines situations. arrayet &arraysont interchangeables dans de nombreux cas.
Carl Norum
21
@Brent: Non. Un tableau est son propre type, ce n'est pas un type spécial de pointeur. Le type d' aentrée int a[10]est int[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.
GManNickG
8
@seand rappelez-vous la règle a [i] == * (a + sizeof (a) * i)
Amir
114

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.

int *fillarr( int arr[] ) { // arr "decays" to type int *
    return arr;
}

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:

int ( &fillarr( int (&arr)[5] ) )[5] { // no decay; argument must be size 5
    return arr;
}

Avec Boost ou C ++ 11, le passage par référence est uniquement facultatif et la syntaxe est moins époustouflante:

array< int, 5 > &fillarr( array< int, 5 > &arr ) {
    return arr; // "array" being boost::array or std::array
}

Le arraymodèle génère simplement un structcontenant un tableau de style C, vous pouvez donc appliquer une sémantique orientée objet tout en conservant la simplicité d'origine du tableau.

Potatoswatter
la source
4
+1 pour donner un exemple de la façon dont un tableau peut être transmis par référence. Mais vous vous trompez en ce que vous ne pouvez pas retourner un tableau par référence. La syntaxe plus simple pour y parvenir est d'utiliser un typedef: 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?
David Rodríguez - dribeas
@David: merci, j'ai eu la mauvaise impression du message Comeau error: function returning array is not allowedqui 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.
Potatoswatter
1
La réponse de chubsdad a la citation correcte de la norme: vous ne pouvez pas retourner un tableau, mais vous pouvez renvoyer une référence ou un pointeur vers un tableau. Les tableaux ne sont pas copiables (en tant que type) et en tant que tels, ils ne peuvent pas être retournés - ce qui impliquerait une copie - et lorsque cette syntaxe est présente, le compilateur convertira l'argument en un pointeur.
David Rodríguez - dribeas
3
@David: C'est vrai. Cette page devient bizarrement longue. Jamais autant de personnes n'ont volontairement écrit autant de fonctions triviales renvoyant un tableau au même endroit.
Potatoswatter
@Potatoswatter Je suis nouveau sur cpp, pouvez-vous expliquer en détail le 2e extrait de code? Je ne suis pas en mesure de le diviser en plusieurs parties par souci de compréhension.
KPMG
23

En C ++ 11, vous pouvez revenir std::array.

#include <array>
using namespace std;

array<int, 5> fillarr(int arr[])
{
    array<int, 5> arr2;
    for(int i=0; i<5; ++i) {
        arr2[i]=arr[i]*2;
    }
    return arr2;
}
cubuspl42
la source
2
Cotation OP:(...) you can consider the array returned arr2, totally another array (...)
cubuspl42
22

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."

int (&fn1(int (&arr)[5]))[5]{     // declare fn1 as returning refernce to array
   return arr;
}

int *fn2(int arr[]){              // declare fn2 as returning pointer to array
   return arr;
}


int main(){
   int buf[5];
   fn1(buf);
   fn2(buf);
}
Chubsdad
la source
7
Votre deuxième fonction renvoie un pointeur sur un int, pas un tableau.
GManNickG
encore une fois, pourquoi retourner le type lorsque le tableau réel est mis à jour à l'intérieur de la fonction? Est-ce une question de bonnes pratiques?
Dan
14

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:

std::vector<int> fillarr( std::vector<int> arr ) {
    // do something
    return arr;
}

Cela fera exactement ce que vous attendez de lui. L'avantage, c'est que l'on std::vectors'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

void fillarr(std::vector<int> &  arr) {
    // modify arr
    // don't return anything
}

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.

std::auto_ptr<std::vector<int> > fillarr( const std::vector<int> & arr) {
    std::auto_ptr<std::vector<int> > myArr(new std::vector<int>);
    // do stuff with arr and *myArr
    return myArr;
}

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 le constmot 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

template <class Iterator>
Iterator fillarr(Iterator arrStart, Iterator arrEnd) {
    Iterator arrIter = arrStart;
    for(;arrIter <= arrEnd; arrIter++)
       ;// do something
    return arrStart;
}

L'utiliser semble un peu étrange si vous n'êtes pas habitué à voir ce style.

vector<int> arr;
vector<int>::iterator foo = fillarr(arr.begin(), arr.end());

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

int arr[100];
int *foo = fillarr(arr, arr+100);

Ce qui ressemble maintenant beaucoup aux exemples de pointeurs simples donnés ailleurs dans cette question.

SingleNegationElimination
la source
La syntaxe est erronée, le &symbole doit apparaître après le type:void fillarr(std::vector<int> & arr)
David Rodríguez - dribeas
9

Ce:

int fillarr(int arr[])

est en fait traité de la même manière que:

int fillarr(int *arr)

Maintenant, si vous voulez vraiment retourner un tableau, vous pouvez changer cette ligne en

int * fillarr(int arr[]){
    // do something to arr
    return arr;
}

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

int fillarr(int arr[]){
   array[0] = 10;
   array[1] = 5;
}

int main(int argc, char* argv[]){
   int arr[] = { 1,2,3,4,5 };

   // arr[0] == 1
   // arr[1] == 2 etc
   int result = fillarr(arr);
   // arr[0] == 10
   // arr[1] == 5    
   return 0;
}

Je suggère que vous souhaitiez peut-être envisager de mettre une longueur dans votre fonction fillarr comme ceci.

int * fillarr(int arr[], int length)

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:

int * fillarr(int arr[], int length){
   for (int i = 0; i < length; ++i){
      // arr[i] = ? // do what you want to do here
   }
   return arr;
}

// then where you want to use it.
int arr[5];
int *arr2;

arr2 = fillarr(arr, 5);

// at this point, arr & arr2 are basically the same, just slightly
// different types.  You can cast arr to a (char*) and it'll be the same.

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

Mat
la source
Utilisez std::copyplus memset, c'est plus sûr et plus facile. (Et tout aussi rapide sinon plus rapide.)
GManNickG
5

pour renvoyer un tableau à partir d'une fonction, définissons ce tableau dans une structure; Donc ça ressemble à ça

struct Marks{
   int list[5];
}

Créons maintenant des variables de la structure de type.

typedef struct Marks marks;
marks marks_list;

Nous pouvons passer un tableau à une fonction de la manière suivante et lui attribuer une valeur:

void setMarks(int marks_array[]){
   for(int i=0;i<sizeof(marks_array)/sizeof(int);i++)
       marks_list.list[i]=marks_array[i];
}

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.

marks getMarks(){
 return marks_list;
}
Sandeep
la source
5

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::vectorou std::array(je ne sais pas si std::arrayc'é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.

std::array<int, 5>& fillarr(std::array<int, 5>& arr)
{
    // (before c++11)
    for(auto it = arr.begin(); it != arr.end(); ++it)
    { /* do stuff */ }

    // Note the following are for c++11 and higher.  They will work for all
    // the other examples below except for the stuff after the Edit.

    // (c++11 and up)
    for(auto it = std::begin(arr); it != std::end(arr); ++it)
    { /* do stuff */ }

    // range for loop (c++11 and up)
    for(auto& element : arr)
    { /* do stuff */ }

    return arr;
}

std::vector<int>& fillarr(std::vector<int>& arr)
{
    for(auto it = arr.begin(); it != arr.end(); ++it)
    { /* do stuff */ }
    return arr;
}

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.

template <size_t N>
int(&fillarr(int(&arr)[N]))[N]
{
    // N is easier and cleaner than specifying sizeof(arr)/sizeof(arr[0])
    for(int* it = arr; it != arr + N; ++it)
    { /* do stuff */ }
    return arr;
}

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:

template <typename T>
using type_t = T;

template <size_t N>
type_t<int(&)[N]> fillarr(type_t<int(&)[N]> arr)
{
    // N is easier and cleaner than specifying sizeof(arr)/sizeof(arr[0])
    for(int* it = arr; it != arr + N; ++it)
    { /* do stuff */ }
    return arr;
}

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:

type_t<int(&)[5]> fillarr(type_t<int(&)[5]> arr)
{
    // Prefer using the compiler to figure out how many elements there are
    // as it reduces the number of locations where you have to change if needed.
    for(int* it = arr; it != arr + sizeof(arr)/sizeof(arr[0]); ++it)
    { /* do stuff */ }
    return arr;
}

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:

template<typename T>
struct type
{
  typedef T type;
};

typename type<int(&)[5]>::type fillarr(typename type<int(&)[5]>::type arr)
{
    // Prefer using the compiler to figure out how many elements there are
    // as it reduces the number of locations where you have to change if needed.
    for(int* it = arr; it != arr + sizeof(arr)/sizeof(arr[0]); ++it)
    { /* do stuff */ }
    return arr;
}

Ce qui recommence à être assez moche, mais au moins est encore plus lisible, bien que cela typenamepuisse être facultatif à l'époque en fonction du compilateur, ce qui se traduit par:

type<int(&)[5]>::type fillarr(type<int(&)[5]>::type arr)
{
    // Prefer using the compiler to figure out how many elements there are
    // as it reduces the number of locations where you have to change if needed.
    for(int* it = arr; it != arr + sizeof(arr)/sizeof(arr[0]); ++it)
    { /* do stuff */ }
    return arr;
}

Et puis bien sûr, vous auriez pu spécifier un type spécifique, plutôt que d'utiliser mon aide.

typedef int(&array5)[5];

array5 fillarr(array5 arr)
{
    // Prefer using the compiler to figure out how many elements there are
    // as it reduces the number of locations where you have to change if needed.
    for(int* it = arr; it != arr + sizeof(arr)/sizeof(arr[0]); ++it)
    { /* do stuff */ }
    return arr;
}

À l' époque, les fonctions libres std::begin()et std::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.

void other_function(type_t<int(&)[5]> x) { /* do something else */ }

void fn()
{
    int array[5];
    other_function(fillarr(array));
}

ou

void fn()
{
    int array[5];
    auto& array2 = fillarr(array); // alias. But why bother.
    int forth_entry = array[4];
    int forth_entry2 = array2[4]; // same value as forth_entry
}

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.

// separate size value
int* fillarr(int* arr, size_t size)
{
    for(int* it = arr; it != arr + size; ++it)
    { /* do stuff */ }
    return arr;
}

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.

// separate end pointer
int* fillarr(int* arr, int* end)
{
    for(int* it = arr; it != end; ++it)
    { /* do stuff */ }
    return arr;
}

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.

// I document that this function will ONLY take 5 elements and 
// return the same array of 5 elements.  If you pass in anything
// else, may nazal demons exit thine nose!
int* fillarr(int* arr)
{
    for(int* it = arr; it != arr + 5; ++it)
    { /* do stuff */ }
    return arr;
}

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.

std::pair<int*, int*> fillarr(std::pair<int*, int*> arr)
{
    for(int* it = arr.first; it != arr.second; ++it)
    { /* do stuff */ }
    return arr; // if you change arr, then return the original arr value.
}

void fn()
{
    int array[5];
    auto array2 = fillarr(std::make_pair(&array[0], &array[5]));

    // Can be done, but you have the original array in scope, so why bother.
    int fourth_element = array2.first[4];
}

ou

void other_function(std::pair<int*, int*> array)
{
    // Can be done, but you have the original array in scope, so why bother.
    int fourth_element = array2.first[4];
}

void fn()
{
    int array[5];
    other_function(fillarr(std::make_pair(&array[0], &array[5])));
}

Assez drôle, c'est très similaire à la façon dont std::initializer_listfonctionnent (c ++ 11), mais ils ne fonctionnent pas dans ce contexte.

Adrian
la source
3

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

     void fillarr(int arr[5])
  {
       for(...);

  }
nada
la source
2
int *fillarr(int arr[])

Vous pouvez toujours utiliser le résultat comme

int *returned_array = fillarr(some_other_array);
if(returned_array[0] == 3)
    do_important_cool_stuff();
Daniel
la source
Je ne pense pas que le «int [] fillarr ...» soit légal. Le 'int * fillarr' est ce que vous utiliseriez en raison de l'équivalence de pointeur de tableau.
2010 à
1

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.

int* func()
{
  int* Arr = new int[100];
  return Arr;
}

int main()
{
  int* ArrResult = func();
  cout << ArrResult[0] << " " << ArrResult[1] << endl;
  return 0;
} 



Shehanmark
la source
0
template<typename T, size_t N>
using ARR_REF = T (&)[N];

template <typename T, size_t N>
ARR_REF<T,N> ArraySizeHelper(ARR_REF<T,N> arr);

#define arraysize(arr) sizeof(ArraySizeHelper(arr))
Nozama
la source
0

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.

  1. Si vous souhaitez renvoyer un tableau à une dimension à partir d'une fonction, vous devez déclarer une fonction renvoyant un pointeur comme dans l'exemple suivant:
int * myFunction()    {
   .
   .
   .
}
  1. C ++ ne préconise pas de renvoyer l'adresse d'une variable locale à l'extérieur de la fonction, vous devez donc définir la variable locale comme variable statique.

En appliquant ces règles sur la question actuelle, nous pouvons écrire le programme comme suit:

# include <iostream>

using namespace std;

int * fillarr( );


int main ()
{

   int *p;

   p = fillarr();

   for ( int i = 0; i < 5; i++ )
       cout << "p[" << i << "] : "<< *(p + i) << endl;

    return 0;
}


int * fillarr( )
{
    static int  arr[5];

    for (int i = 0; i < 5; ++i)
        arr[i] = i;

    return arr;
 }

La sortie sera:

p[0]=0
p[1]=1
p[2]=2
p[3]=3
p[4]=4
MAQ
la source
0

et à propos de:

int (*func())
{
    int *f = new int[10] {1,2,3};

    return f;
}

int fa[10] = { 0 };
auto func2() -> int (*) [10]
{
    return &fa;
}
Alexandr
la source
0

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.

#include <iostream>

using namespace std;

int* func(int ar[])
{
    for(int i=0;i<100;i++) 
        ar[i]=i;
    int *ptr=ar;
    return ptr;
}


int main() {
    int *p;
    int y[100]={0};    
    p=func(y);

    for(int i=0;i<100;i++) 
        cout<<i<<" : "<<y[i]<<'\n';
}

Exécutez-le et vous verrez les changements

Abhishek gaur
la source
1
Veuillez utiliser un libellé anglais approprié (vous allez au lieu de u'll) et omettre les phrases vides comme "copain".
hellow
Aussi: "alors en fait, il est passé comme référence" est faux. La variable yelle-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.
hellow
stackoverflow.com/questions/5573310/… TL; DR "Ainsi, les deux formes sont identiques."
hellow
Oui, c'est techniquement un tableau, vous avez raison, mais ce qui est copié est un pointeur sur le tableau, pas le tableau lui-même.
hellow
0

Voici un exemple complet de ce type de problème à résoudre

#include <bits/stdc++.h>
using namespace std;
int* solve(int brr[],int n)
{
sort(brr,brr+n);
return brr;
}

int main()
{
int n;
cin>>n;
int arr[n];
for(int i=0;i<n;i++)
{
    cin>>arr[i];
}
int *a=solve(arr,n);
for(int i=0;i<n;i++)
{
    cout<<a[i]<<endl;
}

return 0;
}
Shaonsani
la source
-2

Définissez simplement un type [] comme valeur de retour, comme:

        private string[] functionReturnValueArray(string one, string two)
    {

        string[] x = {one, two};


        x[0] = "a";
        x[1] = "b";

        return x;
    }

. . . appel de fonction:

string[] y;
y = functionReturnValueArray(stringOne, stringTwo)
Ricardo Fercher
la source
5
Ce n'est pas du C ++
Adrian