2010-09-15 8 views
19

Wie gebe ich ein mehrdimensionales Array zurück, das in einem privaten Feld versteckt ist?C++ Multidimension-Array von Funktion zurückgeben

class Myclass { 
private: 
int myarray[5][5]; 
public: 
int **get_array(); 
}; 

........ 

int **Myclass::get_array() { 
return myarray; 
} 

kann int (*)[5][5]-int** im Gegenzug test.cpp/Polky/src Linie 73 C/C nicht konvertieren ++ Problem

+4

Was ist Raster? sollte es nicht "Myarray" sein? – woodstok

+3

Die Rückgabe eines direkten Verweises auf ein privates Mitglied ist möglicherweise nicht immer eine gute Idee - Sie brechen damit effektiv die Kapselung, sodass jeder auf Ihr privates Mitglied zugreifen und dieses ändern kann. Dies kann in Ihrem Design akzeptabel sein oder auch nicht. –

+0

@MKchail: Da Justin seit seiner Veröffentlichung dieser Frage nicht online war, habe ich mir die Freiheit genommen, es zu reparieren. – sbi

Antwort

-1

Ändern Ihres int [int] [] 's oder versuchen int mit [,] statt ?

+1

'int [,]' ist nicht gültig C++ –

+3

... und 'int [] []' sollte auch nicht gültig sein. In diesem Fall ist es wichtig, den Unterschied zwischen Arrays und Zeigern zu verstehen. – visitor

+2

@David: Eigentlich ist 'new int [5, 5]' gültig C++, es tut einfach nicht, was man denken könnte - es ist das gleiche wie 'new int [5]' dank dem Komma-Operator :) – fredoverflow

-1
int **Myclass::get_array() { 
return (int**)myarray; 
} 
+1

Nein. Wenn Sie das verwenden, werden Sie Elemente des Arrays als Zeiger neu interpretieren. –

+0

@ Mike Seymour, und das ist wahr, wenn Sie jede Zeile als int * betrachten (wie jeden Vektor von ganzen Zahlen, die int * ist). – rkellerm

4

Um einen Zeiger auf das Array von Arraymitglied zurückkehrt, ist die Art benötigt int (*)[5], nicht int **:

class Myclass { 
private: 
    int myarray[5][5]; 
public: 
    int (*get_array())[5]; 
}; 

int (*Myclass::get_array())[5] { 
    return myarray; 
} 
1

ich diese Funktion Arbeit in C++ 0x automatischen Typ Abzug mit machen verwaltet . Aber ich kann es nicht ohne das schaffen. Native C-Arrays werden in C++ nicht sehr gut unterstützt - ihre Syntax ist äußerst abscheulich. Sie sollten eine Wrapper-Klasse verwenden.

template<typename T, int firstdim, int seconddim> class TwoDimensionalArray { 
    T data[firstdim][seconddim]; 
public: 
    T*& operator[](int index) { 
     return data[index]; 
    } 
    const T*& operator[](int index) const { 
     return data[index]; 
    } 
}; 
class Myclass { 
public: 
    typedef TwoDimensionalArray<int, 5, 5> arraytype; 
private: 
    arraytype myarray; 
public: 
    arraytype& get_array() { 
     return myarray; 
    } 
}; 

int main(int argc, char **argv) { 
    Myclass m; 
    Myclass::arraytype& var = m.get_array(); 
    int& someint = var[0][0]; 
} 

Dieser Code kompiliert einfach gut. Sie können eine vordefinierte Wrapperklasse innerhalb von Boost (boost :: array) erhalten, die den gesamten Shebang unterstützt.

+0

Kompiliert nicht mit GCC: Die ersten Rückgabedaten [index] machen einen nichtkonstanten Verweis von einem rvalue, heißt es. – Cubbi

+0

Und das ist der Fall, ein bloßer Zeiger sollte zurückgegeben werden, kein Verweis auf einen Zeiger. Sonst haben wir zumindest viel an Lesbarkeit gewonnen. Ein kleiner Punkt: Warum "int" für die eigentlichen Template-Typen verwenden? Etwas, das unmöglich negativ sein kann, würde besser mit einem vorzeichenlosen Integer-Typ ausgedrückt werden, denke ich. –

+0

data [index] ist ein lvalue, kein rvalue, ähnlich wie * ptr ist ein lvalue. Nicht, dass die Referenz wirklich notwendig ist, ich denke, es ist von einer früheren Version des Codes, Sie könnten es wahrscheinlich entfernen. – Puppy

22

Ein zweidimensionales Array zerfällt nicht in einen Zeiger auf einen Zeiger auf Ints. Es zerfällt zu einem Zeiger auf Arrays von Ints - das heißt, nur die erste Dimension zerfällt zu einem Zeiger. Der Zeiger zeigt nicht auf int-Zeiger, die, wenn sie inkrementiert werden, um die Größe eines Zeigers vorrücken, sondern auf Felder mit 5 ganzen Zahlen.

class Myclass { 
private: 
    int myarray[5][5]; 
public: 
    typedef int (*pointer_to_arrays)[5]; //typedefs can make things more readable with such awkward types 

    pointer_to_arrays get_array() {return myarray;} 
}; 

int main() 
{ 
    Myclass o; 
    int (*a)[5] = o.get_array(); 
    //or 
    Myclass::pointer_to_arrays b = o.get_array(); 
} 

Ein Zeiger auf Zeiger (int**) verwendet wird, wenn jeder Sub-Array separat zugeordnet ist (das heißt, ursprünglich ein Array von Zeigern hat)

int* p[5]; 
for (int i = 0; i != 5; ++i) { 
    p[i] = new int[5]; 
} 

Hier haben wir eine Reihe von fünf Zeigern, jeder zeigt auf das erste Element in einem separaten Speicherblock, insgesamt 6 verschiedene Speicherblöcke.

In einem zweidimensionalen Array erhalten Sie einen einzigen zusammenhängenden Speicherblock:

int arr[5][5]; //a single block of 5 * 5 * sizeof(int) bytes 

Sie sollten das Speicherlayout dieser Dinge sehen, dass ganz unterschiedlich sind, und daher können diese Dinge nicht zurückgegeben werden und übergeben die gleicher Weg.

+0

+1 danke, große Antwort –

2

Wie gebe ich ein mehrdimensionales Array zurück, das in einem privaten Feld verborgen ist?

Wenn es versteckt sein soll, warum geben Sie es in erster Linie zurück?

Wie auch immer, Sie können keine Arrays aus Funktionen zurückgeben, aber Sie können einen Zeiger auf das erste Element zurückgeben. Was ist das erste Element eines 5x5-Arrays von Ints? Eine Anordnung von 5 Ints, natürlich:

int (*get_grid())[5] 
{ 
    return grid; 
} 

Alternativ können Sie das gesamte Array durch Verweis zurück:

int (&get_grid())[5][5] 
{ 
    return grid; 
} 

...Willkommen in C Deklarator Syntax Hölle ;-)

Darf ich stattdessen std::vector<std::vector<int> > oder boost::multi_array<int, 2> vorschlagen?

16

Es gibt zwei mögliche Arten, die Sie zurückgeben können, um Zugriff auf Ihr internes Array zu erhalten. Der alte C-Stil würde int *[5] zurückgeben, da das Array leicht in einen Zeiger auf das erste Element vom Typ int[5] zerfällt.

int (*foo())[5] { 
    static int array[5][5] = {}; 
    return array; 
} 

Jetzt können Sie auch einen richtigen Verweis auf das interne Array zurück, wäre die einfachste Syntax durch eine typedef sein:

typedef int (&array5x5)[5][5]; 
array5x5 foo() { 
    static int array[5][5] = {}; 
    return array; 
} 

Oder ein wenig umständlichen ohne typedef:

int (&foo())[5][5] { 
    static int array[5][5] = {}; 
    return array; 
} 

Der Vorteil der C++ - Version ist, dass der tatsächliche Typ beibehalten wird und dass die tatsächliche Größe des Arrays auf der Anruferseite bekannt ist.

+0

+1 für die C++ - Version (mit dem richtigen typedef) –

+1

Seien Sie vorsichtig, wie Sie diese typedefs verwenden, manchmal: 'delete [] new array5x5()' (sieht aus wie neu, aber es ist wirklich neu []). –

Verwandte Themen