Wie kann ich ein Array von einer Funktion zurückgeben?

Lesezeit: 8 Minuten

Wie kann ich ein Array von einer Funktion zuruckgeben
eggwegw

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

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

  • Diese Frage wurde als Duplikat einer Frage mit einem sehr ähnlichen Titel geschlossen. Bei dieser Frage ging es jedoch darum, ein Array zurückzugeben die als Argument an die Funktion übergeben wurde. Das ist eine ganz andere Behauptung und bedeutet, dass dies eine andere (und interessantere Frage) ist.

    – Martin Bonner unterstützt Monika

    10. April 2018 um 14:39 Uhr

  • Sie geben a zurück std::array oder std::vector. Nicht ein Array im C-Stil.

    – Jesper Juhl

    18. April 2020 um 15:45 Uhr


Wie kann ich ein Array von einer Funktion zuruckgeben
Simone

int* test();

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

std::vector< int > test();

BEARBEITEN

Irgendwann werde ich klarstellen. Da Sie C++ erwähnt haben, gehe ich mit new[] und delete[] Operatoren, aber es ist dasselbe mit malloc/free.

Im ersten Fall schreibst du so etwas wie:

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

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

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 hier:

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

Und Ihr Kundencode 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 es sich um C++ handelt, std::vector<T> ist eine weit verbreitete Lösung:

std::vector<int> test() {
    std::vector<int> vector(10);
    return vector;
}

Jetzt müssen Sie nicht anrufen delete[]da es vom Objekt behandelt wird und Sie es sicher iterieren können mit:

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

was einfacher und sicherer ist.

  • Ich würde mit der Rückgabe von a gehen std::vector.

    – Daniel Lidström

    24. November 2010 um 8:08 Uhr

  • Ich persönlich denke, dass die Antwort int* test(); auf die Frage “Wie gibt man ein Array in einer C++-Methode zurück?”[sic] ist irreführend, wenn Sie dann nicht erklären, dass es eigentlich kein Array, sondern einen Zeiger zurückgibt.

    – CB Bailey

    24. November 2010 um 9:53 Uhr

  • Ich habe einige notwendige Klarstellungen hinzugefügt.

    – Simone

    24. November 2010 um 10:24 Uhr

  • Ist es nicht effizienter, wenn Sie der Funktion eine Referenz eines Vektors übergeben und die Funktion dann beliebig viele Elemente hinzufügt? Sie müssten dann nicht den gesamten Vektor einschließlich aller Elemente kopieren (was passiert, wenn Sie einen Vektor zurückgeben, oder?)

    – Kapichu

    30. Dezember 2014 um 13:39 Uhr

  • @Kapichu Und wenn RVO fehlschlägt, wird der Vektor verschoben und nicht kopiert.

    – fredoverflow

    4. März 2015 um 11:58 Uhr

1646925008 26 Wie kann ich ein Array von einer Funktion zuruckgeben
Toni Delroy

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

Das klingt wie eine einfache Frage, aber in C++ haben Sie eine ganze Reihe von Optionen. Erstens sollten Sie lieber …

  • std::vector<>die dynamisch auf so viele Elemente anwächst, denen Sie zur Laufzeit begegnen, oder

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

…da sie den Speicher für Sie verwalten, für korrektes Verhalten sorgen und die Dinge erheblich vereinfachen:

std::vector<int> fn()
{
    std::vector<int> x;
    x.push_back(10);
    return x;
}

std::array<int, 2> fn2()  // C++11
{
    return {3, 4};
}

void caller()
{
    std::vector<int> a = fn();
    const std::vector<int>& b = fn(); // extend lifetime but read-only
                                      // b valid until scope exit/return

    std::array<int, 2> c = fn2();
    const std::array<int, 2>& d = fn2();
}

Die Praxis der Erstellung eines const Der Verweis auf die zurückgegebenen Daten kann manchmal eine Kopie vermeiden, aber normalerweise können Sie sich einfach auf die Rückgabewertoptimierung verlassen, oder – z vector aber nicht array – Move-Semantik (eingeführt mit C++11).

Wenn Sie wirklich eine verwenden möchten eingebaut array (im Unterschied zur Standardbibliotheksklasse namens array oben erwähnt), besteht eine Möglichkeit darin, dass der Aufrufer Speicherplatz reserviert und der Funktion mitteilt, ihn 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 Möglichkeit besteht darin, das Array in eine Struktur einzuschließen, die – im Gegensatz zu rohen Arrays – als Wert von einer Funktion zurückgegeben werden kann:

struct X
{
    int x[10];
};

X fn()
{
    X x;
    x.x[0] = 10;
    // ...
    return x;
}

void caller()
{
    X x = fn();
}

Beginnend mit dem oben Gesagten, wenn Sie mit C++03 nicht weiterkommen, möchten Sie es vielleicht in etwas verallgemeinern, das näher an C++11 liegt std::array:

template <typename T, size_t N>
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 Möglichkeit besteht darin, die aufgerufene Funktion Speicher auf dem Heap zuweisen zu lassen:

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 Zeiger”, die das Löschen sicherstellen, wenn die Zeiger auf das Objekt ihren Bereich verlassen. Mit C++11:

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

Wenn Sie bei C++03 festsitzen, ist die beste Option, zu prüfen, ob die Boost-Bibliothek auf Ihrem Computer verfügbar ist: Sie bietet boost::shared_array.

Eine weitere Option besteht darin, statischen Speicher zu reservieren fn()obwohl dies NICHT THREAD SAFE ist und jeden Aufruf bedeutet fn() überschreibt die Daten, die von jedem gesehen werden, der Zeiger von früheren Anrufen behält. Allerdings kann es für einfachen Single-Thread-Code praktisch (und schnell) 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...
}

  • Das glaube ich nicht new[] int(10) ist ein gültiger neuer Ausdruck. Hast du gemeint new int[10] ?

    – CB Bailey

    24. November 2010 um 11:50 Uhr

  • @Charles: Wahrscheinlich hasse ich es, den ganzen verdammten Tag in C# festzustecken und dann zu versuchen, hier etwas zu beantworten … ahhhh … 😉 Macht mir total den Kopf rein.

    – Toni Delroy

    24. November 2010 um 11:59 Uhr


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

Funktionen dürfen keinen Rückgabetyp vom Typ Array oder Funktion haben[…]

Die am häufigsten gewählten Alternativen bestehen darin, einen Wert des Klassentyps zurückzugeben, wobei diese Klasse ein Array enthält, z

struct ArrayHolder
{
    int array[10];
};

ArrayHolder test();

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

Z.B

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

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

Obwohl es möglich ist, eine Referenz oder einen Zeiger auf ein Array zurückzugeben, ist dies äußerst selten, da es sich um eine komplexere Syntax ohne praktischen Vorteil gegenüber einer der oben genannten Methoden handelt.

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

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

Wenn Sie Ihr Array von einer Funktion zurückgeben möchten, müssen Sie sicherstellen, dass die Werte nicht auf dem Stapel gespeichert sind, da sie beim Verlassen der Funktion verschwunden sind.

Machen Sie Ihr Array also entweder statisch oder weisen Sie den Speicher zu (oder übergeben Sie ihn, aber Ihr erster Versuch ist mit einem void-Parameter). Für deine 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 deklarieren? int[] test(ungültig); ???

template <class X>
  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<float> 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;

988290cookie-checkWie kann ich ein Array von einer Funktion zurückgeben?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy