2010-11-24 3 views

Antwort

54

int* test();

aber es wäre "mehr C++" sein, Vektoren zu verwenden:

std::vector<int> test();

EDIT
Ich werde einige Punkte klären. Da Sie C++ erwähnt haben, werde ich mit new[] und delete[] Operatoren gehen, aber es ist das gleiche mit malloc/free.

Im ersten Fall werden Sie so etwas wie schreiben:

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

aber es ist nicht eine gute Idee, weil Client Ihre Funktion ist nicht wirklich die Größe des Arrays nicht wissen, dass Sie zurückkommen, obwohl der Client kann sie mit einem Aufruf von delete[] sicher freigeben.

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

Eine bessere Unterschrift würde dies sein:

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

Und Ihre Kundennummer 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 diese C++ ist, `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 delete[] nennen müssen, da es von dem Objekt behandelt werden, und Sie können es sicher mit iterieren:

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

, die einfacher und sicherer ist.

+2

ich mit der Rückkehr eines 'std :: VECTOR' gehen würde. –

+8

Persönlich denke ich, dass die Antwort "int * test();" auf die Frage "howto ein Array in einer C++ Methode zurückgeben?" [Sic] irreführend ist, wenn Sie dann nicht erklären, dass es tatsächlich kein Array zurückgibt aber ein Zeiger. –

+0

Ich fügte einige notwendige Klärung hinzu. – Simone

2

Nun, wenn Sie Ihr Array von einer Funktion zurückgeben wollen, müssen Sie sicherstellen, dass die Werte nicht auf dem Stapel gespeichert werden, da sie beim Verlassen der Funktion weg sind.

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

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

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

Das klingt wie eine einfache Frage, aber in C++ haben Sie einige Optionen. Erstens sollten Sie bevorzugen ...

  • std::vector<>, die jedoch dynamisch zu viele Elemente wächst man zur Laufzeit auftreten, oder

  • std::array<> (eingeführt mit C++ 11), die immer eine Anzahl von Elementen speichert bei der Kompilierung angegeben,

... als sie Speicher verwalten für Sie, das richtige Verhalten zu gewährleisten und die Dinge erheblich vereinfacht:

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 des einen const Bezug auf die zurückgegebenen Daten erstellen, kann manchmal eine Kopie vermeiden, aber in der Regel verlassen Sie können nur auf Rückgabewert-Optimierung, oder - für vector aber nicht array - Semantik bewegen (eingeführt mit C++ 11) .

Wenn Sie wirklich einen eingebauten Array (im Unterschied zu der Standard-Bibliothek Klasse array oben erwähnte genannt) verwendet werden sollen, ist eine Möglichkeit für den Anrufer Platz zu reservieren und der Funktion sagen, es zu benutzen:

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 weitere Option ist das Array in einer Struktur zu setzen, das - im Gegensatz zu rohen Arrays - ist legal aus einer Funktion von Wert zurückgeben:

struct X 
{ 
    int x[10]; 
}; 

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

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

mit der oben starten, wenn Sie mit stecken C++ 03 Sie möchten es in näher etwas verallgemeinern zu dem C++ 11 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 ist es, die genannte Funktion zuweisen Speicher auf dem Heap haben:

int* fn() 
{ 
    int* p = new int[2]; 
    p[0] = 0; 
    p[1] = 1; 
    return p; 
} 

void caller() 
{ 
    int* p = fn(); 
    // use p... 
    delete[] p; 
} 

zu Um die Verwaltung von Heap-Objekten zu vereinfachen, verwenden viele C++ - Programmierer "Smart Pointer", die das Löschen sicherstellen, wenn die Zeiger auf das Objekt ihre Bereiche 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 auf C++ 03 stecken, ist die beste Option, um zu sehen, wenn die Boost-Bibliothek auf Ihrem Computer verfügbar ist: es bietet boost::shared_array.

Noch eine andere Option ist, etwas statischer Speicher reserviert von fn() zu haben, obwohl dies NICHT GEWINNSICHER ist, und jeder Anruf zu fn() überschreibt die Daten, die von jedem gesehen werden, der Zeiger von vorherigen Anrufen behält. Das heißt, es kann bequem (und schnell) für einfache Single-Thread-Code sein.

+1

Ich glaube nicht, dass 'new [] int (10)' ein gültiger neuer Ausdruck ist. Meinst du "new int [10]"? –

+0

@Charles: wahrscheinlich, ich hasse es, in C stecken zu bleiben, verdammt noch mal, dann versuche etwas hier zu beantworten ... ahhhh ... ;-) Totally geht mein Kopf rein. –

9

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

Funktionen müssen nicht einen Rückgabetyp vom Typ Array oder Funktion haben, [...]

Am häufigsten gewählten Alternativen sind, einen Wert von zurückzukehren Klassentyp, wobei diese Klasse ein Array enthält, z

struct ArrayHolder 
{ 
    int array[10]; 
}; 

ArrayHolder test(); 

Oder einen Zeiger auf das erste Element einer statisch oder dynamisch zugewiesenen Array zurückzukehren, muss die Dokumentation für den Benutzer angeben, ob er braucht, um (und wenn ja, wie er sollte) das Array freigeben, dass der zurückgegebene Zeiger verweist auf.

z.

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

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

Während es möglich ist, eine Referenz oder einen Zeiger auf ein Array zurückzubringen, ist es äußerst selten, da sie eine komplexe Syntax ohne praktischen Vorteil gegenüber jedem der obigen Verfahren ist.

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

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

"Wie kann ich wieder ein Array in einer C++ Methode muss und wie ich es erklären int [] test (void);? ??"

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;