Wie gebe ich ein Array von einer function zurück?

Wie kann ich ein Array von einer Methode zurückgeben und wie muss ich es deklarieren?

int[] test(void); // ?? 

   

int* test();

aber es wäre “mehr C ++” Vektoren zu verwenden:

std::vector< int > test();

BEARBEITEN
Ich werde etwas klarstellen. Da Sie C ++ erwähnt haben, gehe ich mit den new[] Operatoren new[] und delete[] , aber auch mit malloc / free.

Im ersten Fall schreiben Sie etwas wie:

 int* test() { return new int[size_needed]; } 

Aber das ist keine gute Idee, weil der Client Ihrer function die Größe des Arrays, das Sie zurückgeben, nicht wirklich kennt, obwohl der Client sie mit einem Aufruf zum delete[] sicher freigeben kann.

 int* theArray = test(); for (size_t i; i < ???; ++i) { // I don't know what is the array size! // ... } delete[] theArray; // ok. 

Eine bessere Signatur wäre diese:

 int* test(size_t& arraySize) { array_size = 10; return new int[array_size]; } 

Und Ihr Client-Code wäre jetzt:

 size_t theSize = 0; int* theArray = test(theSize); for (size_t i; i < theSize; ++i) { // now I can safely iterate the array // ... } delete[] theArray; // still ok. 

Da dies C ++ ist, ist `std :: vector eine weit verbreitete Lösung:

 std::vector test() { std::vector vector(10); return vector; } 

Jetzt müssen Sie delete[] nicht mehr aufrufen, da es vom Objekt gehandhabt wird, und Sie können es sicher durchlaufen mit:

 std::vector v = test(); std::vector::iterator it = v.begin(); for (; it != v.end(); ++it) { // do your things } 

Das ist einfacher und sicherer.

Wie kann ich ein Array in einer C ++ Methode zurückgeben und wie muss ich es deklarieren? int [] Test (void); ??

Das hört sich nach einer einfachen Frage an, aber in C ++ haben Sie einige Möglichkeiten. Erstens sollten Sie bevorzugen …

  • std::vector<> , die dynamisch zu beliebig vielen Elementen zur Laufzeit wächst, oder

  • std::array<> (eingeführt mit C ++ 11), das immer eine Anzahl von Elementen speichert, die zur Kompilierzeit angegeben wurden,

… wie sie Speicher für Sie verwalten, richtiges Verhalten sicherstellen und die Dinge erheblich vereinfachen:

 std::vector fn() { std::vector x; x.push_back(10); return x; } std::array fn2() // C++11 { return {3, 4}; } void caller() { std::vector a = fn(); const std::vector& b = fn(); // extend lifetime but read-only // b valid until scope exit/return std::array c = fn2(); const std::array& d = fn2(); } 

Die Praxis, eine const auf die zurückgegebenen Daten zu erstellen, kann manchmal eine Kopie vermeiden, aber normalerweise können Sie sich nur auf die Rückgabewertoptimierung verlassen oder – für vector aber nicht für array – die Semantik verschieben (eingeführt mit C ++ 11).

Wenn Sie wirklich ein eingebautes Array verwenden möchten (im Gegensatz zur oben erwähnten Standardbibliotheksklasse namens array ), besteht eine Möglichkeit für den Aufrufer darin, Speicherplatz zu reservieren und der function mitzuteilen, sie zu verwenden:

 void fn(int x[], int n) { for (int i = 0; i < n; ++i) x[i] = n; } void caller() { // local space on the stack - destroyed when caller() returns int x[10]; fn(x, sizeof x / sizeof x[0]); // or, use the heap, lives until delete[](p) called... int* p = new int[10]; fn(p, 10); } 

Eine andere Option besteht darin, das Array in eine Struktur zu verpacken, die - im Gegensatz zu RAW-Arrays - nach Wert aus einer function zurückgegeben werden kann:

 struct X { int x[10]; }; X fn() { X x; xx[0] = 10; // ... return x; } void caller() { X x = fn(); } 

Beginnend mit dem oben genannten, wenn Sie mit C ++ 03 stecken bleiben, möchten Sie es möglicherweise in etwas näher an das C ++ 11 std::array verallgemeinern:

 template  struct array { T& operator[](size_t n) { return x[n]; } const T& operator[](size_t n) const { return x[n]; } size_t size() const { return N; } // iterators, constructors etc.... private: T x[N]; }; 

Eine andere Option ist, dass die aufgerufene function Speicher auf dem Heap reserviert:

 int* fn() { int* p = new int[2]; p[0] = 0; p[1] = 1; return p; } void caller() { int* p = fn(); // use p... delete[] p; } 

Um die Verwaltung von Heap-Objekten zu vereinfachen, verwenden viele C ++ - Programmierer "intelligente pointers", die das Löschen sicherstellen, wenn die pointers auf das Objekt ihre Bereiche verlassen. Mit C ++ 11:

 std::shared_ptr p(new int[2], [](int* p) { delete[] p; } ); std::unique_ptr p(new int[3]); 

Wenn Sie in C ++ 03 stecken bleiben, sollten Sie boost::shared_array ob die Boost-Bibliothek auf Ihrem Computer verfügbar ist: boost::shared_array .

Eine weitere Option besteht darin, statischen Speicher durch fn() reserviert zu haben, obwohl dies NICHT THREAD SAFE ist und bedeutet, dass jeder Aufruf von fn() die Daten überschreibt, die von jedem gesehen werden, der pointers von vorherigen Aufrufen behält. Das heißt, es kann bequem (und schnell) für einfache Single-Thread-Code sein.

 int* fn(int n) { static int x[2]; // clobbered by each call to fn() x[0] = n; x[1] = n + 1; return x; // every call to fn() returns a pointer to the same static x memory } void caller() { int* p = fn(3); // use p, hoping no other thread calls fn() meanwhile and clobbers the values... // no clean up necessary... } 

Es ist nicht möglich, ein Array von einer C ++ – function zurückzugeben. 8.3.5 [dcl.fct] / 6:

functionen dürfen keinen Rückgabetyp vom Typ array oder function haben […]

Die am häufigsten gewählten Alternativen sind die Rückgabe eines Wertes des classntyps, wobei diese class ein Array enthält, z

 struct ArrayHolder { int array[10]; }; ArrayHolder test(); 

Oder um einen pointers auf das erste Element eines statisch oder dynamisch zugewiesenen Arrays zurückzugeben, muss die Dokumentation dem Benutzer anzeigen, ob er das Array, auf das der zurückgegebene pointers zeigt, aufheben muss (und falls ja wie).

Z.B

 int* test2() { return new int[10]; } int* test3() { static int array[10]; return array; } 

Es ist zwar möglich, einen Verweis oder einen pointers auf ein Array zurückzugeben, es ist jedoch äußerst selten, da es sich um eine komplexere Syntax handelt, die keinen praktischen Vorteil gegenüber den oben genannten Methoden bietet.

 int (&test4())[10] { static int array[10]; return array; } int (*test5())[10] { static int array[10]; return &array; } 

Nun, wenn Sie Ihr Array von einer function zurückgeben möchten, müssen Sie sicherstellen, dass die Werte nicht auf dem Stapel gespeichert sind, da sie beim Verlassen der function nicht mehr vorhanden sind.

Also machen Sie entweder Ihr Array statisch oder weisen Sie den Speicher zu (oder übergeben Sie es, aber Ihr erster Versuch ist mit einem void-Parameter). Für Ihre Methode würde ich es so definieren:

 int *gnabber(){ static int foo[] = {1,2,3} return foo; } 

“Wie kann ich ein Array in einer C ++ Methode zurückgeben und wie muss ich es erklären? int [] test (void); ??”

 template  class Array { X *m_data; int m_size; public: // there constructor, destructor, some methods int Get(X* &_null_pointer) { if(!_null_pointer) { _null_pointer = new X [m_size]; memcpy(_null_pointer, m_data, m_size * sizeof(X)); return m_size; } return 0; } }; 

nur für Int

 class IntArray { int *m_data; int m_size; public: // there constructor, destructor, some methods int Get(int* &_null_pointer) { if(!_null_pointer) { _null_pointer = new int [m_size]; memcpy(_null_pointer, m_data, m_size * sizeof(int)); return m_size; } return 0; } }; 

Beispiel

 Array array; float *n_data = NULL; int data_size; if(data_size = array.Get(n_data)) { // work with array } delete [] n_data; 

Beispiel für int

 IntArray array; int *n_data = NULL; int data_size; if(data_size = array.Get(n_data)) { // work with array } delete [] n_data;