Array in einer Funktion zurückgeben

212

Ich habe ein Array int arr[5], das an eine Funktion übergeben wird fillarr(int arr[]):

int fillarr(int arr[])
{
    for(...);
    return arr;
}
  1. Wie kann ich dieses Array zurückgeben?
  2. Wie werde ich es verwenden, sagen wir, ich habe einen Zeiger zurückgegeben, wie werde ich darauf zugreifen?
Ismail Marmoush
quelle
46
Genau genommen müssen Sie in diesem Zusammenhang das Array nicht zurückgeben, da das Array als Referenz übergeben wird, sodass Änderungen an Elementen innerhalb von 'arr' außerhalb der Funktion angezeigt werden.
BuggerMe
12
Das Zurückgeben des Arrays ist praktisch für Verkettungsfunktionen.
Seand
5
Solange Sie nicht den Fehler machen, ein Array auf dem Stapel zu erstellen und einen Zeiger darauf zurückzugeben.
Detly
2
@ismail: Es kann kein neues Array zurückgegeben werden, es sei denn, dieses Array wurde dynamisch zugewiesen. Und wenn das der Fall ist, verwenden Sie std::vector.
GManNickG
4
@BuggerMe: Arrays werden nicht als Referenz übergeben (es sei denn, Sie fordern sie mit einer viel lustigeren Syntax an). Im Code zerfällt das Array in einen Zeiger auf das erste Element und dieser wird an die Funktion übergeben. Die 5Signatur in der Funktion wird vom Compiler verworfen.
David Rodríguez - Dribeas

Antworten:

204

In diesem Fall kann Ihre Array-Variable arrdurch eine implizite Konvertierung auch als Zeiger auf den Anfang des Blocks Ihres Arrays im Speicher behandelt werden. Diese Syntax, die Sie verwenden:

int fillarr(int arr[])

Ist nur syntaktischer Zucker. Sie könnten es wirklich dadurch ersetzen und es würde immer noch funktionieren:

int fillarr(int* arr)

Im gleichen Sinne ist das, was Sie von Ihrer Funktion zurückgeben möchten, tatsächlich ein Zeiger auf das erste Element im Array:

int* fillarr(int arr[])

Und Sie können es trotzdem wie ein normales Array verwenden:

int main()
{
  int y[10];
  int *a = fillarr(y);
  cout << a[0] << endl;
}
Brent schreibt Code
quelle
45
Zur Verdeutlichung ist diese "klassische C ++ - Anweisung" falsch. Arrays sind keine Zeiger.
GManNickG
25
Denken Sie an die
8
@ Brent Nash, nein. Ein Array ist ein Array. Ein Zeiger auf den Anfang des Arrays ist ein Zeiger. Es kommt einfach vor, dass der Compiler syntaktischen Zucker hat, der in bestimmten Situationen die Übersetzung für Sie übernimmt. arrayund &arraysind in vielen Fällen austauschbar.
Carl Norum
20
@Brent: Nein. Ein Array ist ein eigener Typ, keine spezielle Art von Zeiger. Die Art von ain int a[10]ist int[10]. Was Sie sagen können, ist, dass Arrays in Zeiger auf ihr erstes Element "zerfallen". (Dies ist eine implizite Array-zu-Zeiger-Konvertierung.) Dann würde Ihre Antwort in die Richtung gehen, die meine tut. Wenn Sie Ihre Antwort bearbeiten, um zwischen Arrays, Array-zu-Zeiger-Konvertierung und Zeigern zu unterscheiden, lösche ich meine Antwort, da sie dieselben Kerninformationen enthalten würden und Sie der Erste waren.
GManNickG
8
@ Sean und erinnere mich an die a [i] == * (a + Größe von (a) * i) Regel
Amir
114

C ++ - Funktionen können keine Arrays im C-Stil nach Wert zurückgeben. Am nächsten ist es, einen Zeiger zurückzugeben. Darüber hinaus wird ein Array-Typ in der Argumentliste einfach in einen Zeiger konvertiert.

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

Sie können es verbessern, indem Sie Array-Referenzen für das Argument und die Rückgabe verwenden, wodurch der Zerfall verhindert wird:

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

Bei Boost oder C ++ 11 ist die Referenzübergabe nur optional und die Syntax ist weniger umwerfend:

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

Die arrayVorlage generiert einfach ein structArray mit einem C-Stil, sodass Sie eine objektorientierte Semantik anwenden und dabei die ursprüngliche Einfachheit des Arrays beibehalten können.

Kartoffelklatsche
quelle
4
+1 für ein Beispiel, wie ein Array als Referenz übergeben werden kann. Sie irren sich jedoch darin, dass Sie ein Array nicht als Referenz zurückgeben können. Die einfachste Syntax, um dies zu erreichen, ist die Verwendung eines typedef: typedef int array[5]; array& foo();Sie benötigen jedoch nicht einmal das typedef, wenn Sie dies schreiben möchten: int (&foo())[5] { static int a[5] = {}; return a; }Das Beispiel in der Frage wäre : int (&foo( int (&a)[5] ))[5] { return a; }. Einfach, nicht wahr?
David Rodríguez - Dribeas
@ David: Danke, ich habe den falschen Eindruck von der Comeau-Nachricht erhalten, error: function returning array is not alloweddie auftritt, wenn Sie die äußeren Parens in der Nicht-Typedef-Syntax weglassen. Glücklicherweise habe ich heute die Rechts-Links-Regel auf eine andere Frage überprüft und es geschafft, das Richtige zu konstruieren ... nachdem ich gesehen habe, dass es möglich ist ... bevor ich gesehen habe, dass Sie den Code gegeben haben: vP.
Potatoswatter
1
Die Antwort von chubsdad hat das richtige Zitat aus dem Standard: Sie können kein Array zurückgeben, aber Sie können eine Referenz oder einen Zeiger auf ein Array zurückgeben. Arrays sind nicht kopierbar (als Typ) und können daher nicht zurückgegeben werden - was eine Kopie implizieren würde - und wenn diese Syntax vorhanden ist, konvertiert der Compiler das Argument in einen Zeiger.
David Rodríguez - Dribeas
3
@ David: So ist es auch. Diese Seite wird bizarr lang. Noch nie haben so viele Leute freiwillig so viele triviale Funktionen geschrieben, die ein Array an einem Ort zurückgeben.
Potatoswatter
@Potatoswatter Ich bin neu bei cpp. Kannst du das 2. Code-Snippet im Detail erklären? Ich bin nicht in der Lage, es zum besseren Verständnis in Teile zu zerlegen.
KPMG
23

In C ++ 11 können Sie zurückkehren 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
quelle
2
Zitat OP:(...) you can consider the array returned arr2, totally another array (...)
cubuspl42
22

$ 8.3.5 / 8 Staaten-

"Funktionen dürfen keinen Rückgabetyp vom Typ Array oder Funktion haben, obwohl sie einen Rückgabetyp vom Typ Zeiger oder Verweis auf solche Dinge haben können. Es darf keine Arrays von Funktionen geben, obwohl es Arrays von Zeigern auf Funktionen geben kann."

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
quelle
7
Ihre zweite Funktion gibt einen Zeiger auf intein Array zurück.
GManNickG
Warum sollte der Typ zurückgegeben werden, wenn das tatsächliche Array innerhalb der Funktion aktualisiert wird? Ist es eine Frage der besten Praxis?
Dan
14

Die Antwort hängt möglicherweise davon ab, wie Sie diese Funktion verwenden möchten. Lassen Sie uns für die einfachste Antwort entscheiden, dass Sie anstelle eines Arrays wirklich einen Vektor wünschen. Vektoren sind schön, weil das Aussehen für die ganze Welt wie langweilige, gewöhnliche Werte ist, die Sie in regulären Zeigern speichern können. Wir werden uns andere Optionen ansehen und warum Sie sie später wollen:

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

Dies wird genau das tun, was Sie erwarten. Der Vorteil ist, std::vectordass alles sauber gehandhabt wird. Der Nachteil ist, dass dadurch eine sehr große Datenmenge kopiert wird, wenn Ihr Array groß ist. Tatsächlich kopiert es jedes Element des Arrays zweimal. Zuerst wird der Vektor kopiert, damit die Funktion ihn als Parameter verwenden kann. dann kopiert es es erneut, um es an den Anrufer zurückzugeben. Wenn Sie den Vektor selbst verwalten können, können Sie die Dinge viel einfacher erledigen. (Es kann ein drittes Mal kopiert werden, wenn der Anrufer es in einer Variablen speichern muss, um mehr Berechnungen durchzuführen.)

Es sieht so aus, als ob Sie wirklich nur versuchen, eine Sammlung zu füllen. Wenn Sie keinen bestimmten Grund haben, eine neue Instanz einer Sammlung zurückzugeben, tun Sie dies nicht. wir können es so machen

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

Auf diese Weise erhalten Sie einen Verweis auf das an die Funktion übergebene Array, keine private Kopie davon. Alle Änderungen, die Sie am Parameter vornehmen, werden vom Aufrufer angezeigt. Sie könnten einen Verweis darauf zurückgeben, wenn Sie möchten, aber das ist keine wirklich gute Idee, da dies impliziert, dass Sie etwas anderes bekommen als das, was Sie bestanden haben.

Wenn Sie wirklich eine neue Instanz der Sammlung benötigen, diese aber nicht auf dem Stapel haben möchten (und das damit verbundene Kopieren), müssen Sie einen Vertrag für die Behandlung dieser Instanz erstellen. Der einfachste Weg, dies zu tun, ist die Verwendung eines intelligenten Zeigers, der die referenzierte Instanz so lange in der Nähe hält, wie jemand daran festhält. Es geht sauber weg, wenn es außerhalb des Anwendungsbereichs liegt. Das würde so aussehen.

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;
}

Die Verwendung *myArrfunktioniert größtenteils identisch mit der Verwendung eines einfachen Vanillevektors. In diesem Beispiel wird auch die Parameterliste durch Hinzufügen des constSchlüsselworts geändert. Jetzt erhalten Sie eine Referenz, ohne sie zu kopieren, aber Sie können sie nicht ändern, sodass der Anrufer weiß, dass sie dieselbe ist wie vor dem Aufrufen der Funktion.

All dies ist gut, aber idiomatisches C ++ funktioniert selten mit Sammlungen als Ganzes. Normalerweise verwenden Sie Iteratoren für diese Sammlungen. das würde eher so aussehen

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

Die Verwendung sieht etwas seltsam aus, wenn Sie diesen Stil nicht gewohnt sind.

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

foo zeigt jetzt auf den Anfang des Modifizierten arr.

Das Schöne daran ist, dass es auf Vektoren genauso gut funktioniert wie auf einfachen C-Arrays und vielen anderen Arten von Sammlungen

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

Was jetzt sehr nach den einfachen Zeigerbeispielen aussieht, die an anderer Stelle in dieser Frage gegeben wurden.

SingleNegationElimination
quelle
Die Syntax ist falsch, das &Symbol muss nach dem Typ erscheinen:void fillarr(std::vector<int> & arr)
David Rodríguez - Dribeas
9

Dies:

int fillarr(int arr[])

wird tatsächlich genauso behandelt wie:

int fillarr(int *arr)

Wenn Sie nun wirklich ein Array zurückgeben möchten, können Sie diese Zeile in ändern

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

Es gibt nicht wirklich ein Array zurück. Sie geben einen Zeiger auf den Anfang der Array-Adresse zurück.

Denken Sie jedoch daran, dass Sie beim Übergeben des Arrays nur einen Zeiger übergeben. Wenn Sie also die Array-Daten ändern, ändern Sie tatsächlich die Daten, auf die der Zeiger zeigt. Bevor Sie das Array übergeben, müssen Sie daher feststellen, dass Sie das geänderte Ergebnis bereits außen haben.

z.B

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;
}

Ich schlage vor, Sie möchten vielleicht eine Länge in Ihre Fillarr-Funktion wie diese einfügen.

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

Auf diese Weise können Sie die Länge verwenden, um das Array auf seine Länge zu füllen, egal was es ist.

Um es tatsächlich richtig zu benutzen. Mach so etwas:

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.

Wenn Sie das Array nur auf einige Standardwerte setzen möchten, sollten Sie die integrierte Memset-Funktion verwenden.

so etwas wie: memset ((int *) & arr, 5, sizeof (int));

Während ich beim Thema bin. Sie sagen, Sie verwenden C ++. Schauen Sie sich die Verwendung von STL-Vektoren an. Ihr Code ist wahrscheinlich robuster.

Es gibt viele Tutorials. Hier ist eine, die Ihnen eine Vorstellung davon gibt, wie Sie sie verwenden können. http://www.yolinux.com/TUTORIALS/LinuxTutorialC++STL.html

Matt
quelle
Verwendung std::copyvorbei memset, es ist sicherer und einfacher. (Und genauso schnell, wenn nicht schneller.)
GManNickG
5

Um ein Array von einer Funktion zurückzugeben, definieren wir dieses Array in einer Struktur. Es sieht also ungefähr so ​​aus

struct Marks{
   int list[5];
}

Lassen Sie uns nun Variablen der Typstruktur erstellen.

typedef struct Marks marks;
marks marks_list;

Wir können ein Array auf folgende Weise an eine Funktion übergeben und ihr einen Wert zuweisen:

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

Wir können das Array auch zurückgeben. Um das Array zurückzugeben, sollte der Rückgabetyp der Funktion vom Strukturtyp sein, dh Markierungen. Dies liegt daran, dass wir in Wirklichkeit die Struktur übergeben, die das Array enthält. Der endgültige Code könnte also so aussehen.

marks getMarks(){
 return marks_list;
}
Sandeep
quelle
5

Dies ist eine ziemlich alte Frage, aber ich werde meine 2 Cent eingeben, da es viele Antworten gibt, aber keine, die alle möglichen Methoden klar und präzise zeigt (nicht sicher über das prägnante Bit, da dies eine bekam etwas außer Kontrolle geraten. TL; DR 😉).

Ich gehe davon aus, dass das OP das übergebene Array ohne Kopieren zurückgeben wollte, um es direkt an den Aufrufer zu übergeben und an eine andere Funktion zu übergeben, damit der Code schöner aussieht.

Wenn Sie ein Array wie dieses verwenden, wird es jedoch in einen Zeiger zerfallen und vom Compiler wie ein Array behandelt. Dies kann zu subtilen Fehlern führen, wenn Sie ein Array wie übergeben, wobei die Funktion erwartet, dass es 5 Elemente enthält, Ihr Anrufer jedoch tatsächlich eine andere Nummer übergibt.

Es gibt einige Möglichkeiten, wie Sie besser damit umgehen können. Übergeben Sie ein std::vectoroder std::array(nicht sicher, ob std::arrayes 2010 war, als die Frage gestellt wurde). Sie können das Objekt dann als Referenz übergeben, ohne das Objekt kopieren / verschieben zu müssen.

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;
}

Wenn Sie jedoch darauf bestehen, mit C-Arrays zu spielen, verwenden Sie eine Vorlage, in der die Informationen über die Anzahl der Elemente im Array gespeichert sind.

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;
}

Außer, das sieht ziemlich hässlich aus und ist super schwer zu lesen. Ich benutze jetzt etwas, um mit dem zu helfen, was es 2010 nicht gab, was ich auch für Funktionszeiger verwende:

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;
}

Dies bewegt den Typ dahin, wo man ihn erwarten würde, und macht ihn weitaus lesbarer. Die Verwendung einer Vorlage ist natürlich überflüssig, wenn Sie nur 5 Elemente verwenden möchten. Sie können sie also natürlich hart codieren:

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;
}

Wie gesagt, mein type_t<>Trick hätte zu dem Zeitpunkt, als diese Frage gestellt wurde, nicht funktioniert. Das Beste, was Sie sich damals erhofft hatten, war die Verwendung eines Typs in einer Struktur:

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;
}

Was wieder ziemlich hässlich aussieht, aber zumindest noch besser lesbar ist, obwohl das typenamedamals je nach Compiler optional gewesen sein könnte, was zu Folgendem führte:

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;
}

Und dann hätten Sie natürlich einen bestimmten Typ angeben können, anstatt meinen Helfer zu verwenden.

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;
}

Damals die freien Funktionen std::begin()und std::end()nicht existierte, obwohl sein könnten leicht umgesetzt werden . Dies hätte eine sicherere Iteration über das Array ermöglicht, da sie auf einem C-Array sinnvoll sind, jedoch nicht auf einem Zeiger.

Für den Zugriff auf das Array können Sie es entweder an eine andere Funktion übergeben, die denselben Parametertyp verwendet, oder einen Alias ​​erstellen (was nicht viel Sinn macht, da Sie bereits das Original in diesem Bereich haben). Der Zugriff auf eine Array-Referenz entspricht dem Zugriff auf das ursprüngliche Array.

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

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

oder

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
}

Zusammenfassend ist es am besten, einen Array-Zerfall in einen Zeiger nicht zuzulassen, wenn Sie beabsichtigen, darüber zu iterieren. Es ist nur eine schlechte Idee, da es den Compiler davon abhält, Sie davor zu schützen, sich in den Fuß zu schießen, und Ihren Code schwerer lesbar macht. Versuchen Sie immer, dem Compiler zu helfen, indem Sie die Typen so lange wie möglich beibehalten, es sei denn, Sie haben einen sehr guten Grund, dies nicht zu tun.

Bearbeiten

Oh, und der Vollständigkeit halber können Sie zulassen, dass es sich zu einem Zeiger verschlechtert, aber dies entkoppelt das Array von der Anzahl der darin enthaltenen Elemente. Dies geschieht häufig in C / C ++ und wird normalerweise durch Übergeben der Anzahl der Elemente im Array verringert. Der Compiler kann Ihnen jedoch nicht helfen, wenn Sie einen Fehler machen und den falschen Wert an die Anzahl der Elemente übergeben.

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

Anstatt die Größe zu übergeben, können Sie den Endzeiger übergeben, der auf einen nach dem Ende Ihres Arrays zeigt. Dies ist nützlich, da es sich um etwas handelt, das näher an den Standardalgorithmen liegt, die einen Anfangs- und einen Endzeiger verwenden. Was Sie jedoch zurückgeben, ist jetzt nur etwas, an das Sie sich erinnern müssen.

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

Alternativ können Sie dokumentieren, dass diese Funktion nur 5 Elemente benötigt, und hoffen, dass der Benutzer Ihrer Funktion nichts Dummes tut.

// 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;
}

Beachten Sie, dass der Rückgabewert seinen ursprünglichen Typ verloren hat und zu einem Zeiger herabgesetzt wird. Aus diesem Grund sind Sie jetzt allein, um sicherzustellen, dass Sie das Array nicht überlaufen.

Sie könnten ein übergeben std::pair<int*, int*>, das Sie für Anfang und Ende verwenden und das weitergeben können, aber dann sieht es wirklich nicht mehr wie ein Array aus.

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];
}

oder

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])));
}

Komischerweise ist dies der std::initializer_listArbeitsweise (c ++ 11) sehr ähnlich , aber sie funktionieren in diesem Kontext nicht.

Adrian
quelle
3

Der einfachste Weg, dies zu tun, besteht darin, es als Referenz zurückzugeben. Selbst wenn Sie das Symbol '&' nicht schreiben, wird es automatisch als Referenz zurückgegeben

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

  }
nada
quelle
2
int *fillarr(int arr[])

Sie können das Ergebnis weiterhin wie verwenden

int *returned_array = fillarr(some_other_array);
if(returned_array[0] == 3)
    do_important_cool_stuff();
Daniel
quelle
Ich denke nicht, dass das 'int [] fillarr ...' legal ist. Das 'int * fillarr' ist das, was Sie aufgrund der Array-Zeiger-Äquivalenz verwenden würden.
Seand
1

Wie oben erwähnt sind die Pfade korrekt. Aber ich denke, wenn wir nur eine lokale Array-Variable einer Funktion zurückgeben, gibt sie manchmal Müllwerte als ihre Elemente zurück.

Um zu vermeiden, dass ich das Array dynamisch erstellen und fortfahren musste. Welches ist so etwas.

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

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



Shehanmark
quelle
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
quelle
0

Quelle: https://www.tutorialspoint.com/cplusplus/cpp_return_arrays_from_functions.htm

In C ++ kann nicht ein gesamtes Array als Argument für eine Funktion zurückgegeben werden. Sie können jedoch einen Zeiger auf ein Array zurückgeben, indem Sie den Namen des Arrays ohne Index angeben.

  1. Wenn Sie ein eindimensionales Array von einer Funktion zurückgeben möchten, müssen Sie eine Funktion deklarieren, die einen Zeiger zurückgibt, wie im folgenden Beispiel:
int * myFunction()    {
   .
   .
   .
}
  1. C ++ empfiehlt nicht, die Adresse einer lokalen Variablen außerhalb der Funktion zurückzugeben, sodass Sie die lokale Variable als statische Variable definieren müssten.

Wenn wir diese Regeln auf die aktuelle Frage anwenden, können wir das Programm wie folgt schreiben:

# 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;
 }

Die Ausgabe wird sein:

p[0]=0
p[1]=1
p[2]=2
p[3]=3
p[4]=4
MAQ
quelle
0

und was ist mit:

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

    return f;
}

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

Wenn Sie ein Array innerhalb einer Funktion übergeben, wird der Zeiger auf das ursprüngliche Array im Funktionsparameter übergeben, und somit werden die am Array innerhalb dieser Funktion vorgenommenen Änderungen tatsächlich am ursprünglichen Array vorgenommen.

#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';
}

Führen Sie es aus und Sie werden die Änderungen sehen

Abhishek Gaur
quelle
1
Bitte verwenden Sie den richtigen englischen Wortlaut (Sie werden anstelle von Ihnen) und lassen Sie leere Sätze wie "Kumpel" weg.
Gelb
Auch: "dann wird es tatsächlich als Referenz übergeben" ist falsch. Die Variable yselbst wird als Kopie von sich selbst übergeben. Da es sich jedoch um einen Zeiger handelt, werden Sie direkt mit dem Array arbeiten. Bitte bearbeiten Sie Ihre Antwort.
Gelb
stackoverflow.com/questions/5573310/… TL; DR "Somit sind die beiden Formen identisch."
Gelb
Ja, es ist technisch gesehen ein Array, Sie haben Recht, aber was kopiert wird, ist ein Zeiger auf das Array, nicht auf das Array selbst.
Gelb
0

Hier ist ein vollständiges Beispiel für diese Art von Problem, das gelöst werden muss

#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
quelle
-2

Definieren Sie einfach einen Typ [] als Rückgabewert, wie:

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

        string[] x = {one, two};


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

        return x;
    }

. . . Funktionsaufruf:

string[] y;
y = functionReturnValueArray(stringOne, stringTwo)
Ricardo Fercher
quelle
5
Dies ist nicht C ++
Adrian