Darf ein Array als Referenz übergeben werden?
void foo(double& *bar)
Scheint, dass mein Compiler nein sagt. Warum? Was ist der richtige Weg, um ein Array als Referenz zu übergeben? Oder eine Abhilfe? Ich habe ein Array-Argument, das meine Methode ändern und anschließend abrufen sollte. Alternativ könnte ich dieses Array zu einem Klassenmitglied machen, was gut funktioniert, aber viele Nachteile für einen anderen Teil meines Codes hat (den ich vermeiden möchte).
Danke und Grüße.
std::vector
oder ähnliches zu verwenden?std::vector
ist offensichtlich überlegen, wenn die Größe dynamisch / unbekannt ist, aber in Fällen, in denen die Größe immer gleich ist, wäre dies übertrieben undstd::array
löst stattdessen die syntaktische Hässlichkeit auf und verleiht gleichzeitig Wertesemantik.Antworten:
Arrays können eigentlich nur als Referenz übergeben werden:
void foo(double (&bar)[10]) { }
Dies hindert Sie daran, Dinge zu tun wie:
double arr[20]; foo(arr); // won't compile
Um ein Array beliebiger Größe übergeben zu können
foo
, machen Sie es zu einer Vorlage und erfassen Sie die Größe des Arrays zur Kompilierungszeit:template<typename T, size_t N> void foo(T (&bar)[N]) { // use N here }
Sie sollten ernsthaft in Betracht ziehen, zu verwenden
std::vector
, oder wenn Sie einen Compiler haben, der c ++ 11 unterstütztstd::array
.quelle
foo
das Array an übergeben wurde, zerfällt es in einen Zeiger." Nein, und da Sie nur ein Array von 10 Elementen übergeben können, benötigen Sie keine weiteren Informationen zur Größe. (Und noch einmal, Sie können kein Array an übergebenvoid foo( double*& )
; die Ergebnisse einer impliziten Konvertierung sind ein r-Wert und können nicht verwendet werden, um einen Verweis auf Nicht-Konstante zu initialisieren. Sie müssen verwendenvoid foo( double *const & );
.void foo(T &bar[N])
in meiner Vorlage gemacht - aber das bedeutet eigentlich "ein Array von Referenzen" und nicht "Verweis auf Array".std::vector
(von der richtigen Größe) haben, wie würden Sie den Inhalt des Vektors (möglicherweise erhalten überstd::vector::data()
) in diesen Array-Typ umwandeln? Wie lautet die Syntax für eine feste Arraygröße in einem Typparameter (dh zur Verwendung mitstatic_cast<>
)?reinterpret_cast
dass ein dynamisch zugewiesenes Array (ohne intrinsische Größe nach der Zuweisung) als automatisches Array mit fester Größe behandelt wird. Außerdem ist das die falsche Frage: Die richtige Frage wäre "Wie kann ich meinen Code umgestalten, um mit beiden Containertypen zu arbeiten?", Und die Antwort lautet Vorlagen und Iteratoren / Bereiche oder, da Sie sagten, die Größe ist fest, eine Funktion das braucht nur einen Datenzeiger / Ref und codiert die Größe fest (oder wenn die Größe variieren könnte, einen Daten- /span
Ja, aber wenn Argumente für eine Referenz übereinstimmen, ist das implizite Array zum Zeiger nicht automatisch. Sie benötigen also Folgendes:
void foo( double (&array)[42] );
oder
void foo( double (&array)[] );
Beachten Sie jedoch, dass bei der Zuordnung,
double [42]
unddouble []
sind verschiedene Typen. Wenn Sie ein Array mit einer unbekannten Dimension haben, stimmt es mit dem zweiten, aber nicht mit dem ersten überein, und wenn Sie ein Array mit 42 Elementen haben, stimmt es mit dem ersten, aber nicht mit dem zweiten überein . (Letzteres ist meiner Meinung nach sehr kontraintuitiv.)Im zweiten Fall müssen Sie die Dimension ebenfalls übergeben, da es keine Möglichkeit gibt, sie wiederherzustellen, sobald Sie sich in der Funktion befinden.
quelle
double []
unddouble [42]
es handelt sich um zwei verschiedene Typen. Das einzige, was Sie an die letztere Form übergeben könnten, wäre ein Array unbekannter Länge, z. B.extern double d[];
oder ein solches schränkt die Benutzerfreundlichkeit ein.)Wenn Sie nur die Elemente ändern möchten:
void foo(double *bar);
reicht.
Wenn Sie die Adresse in (zB :) ändern möchten,
realloc
dies jedoch für Arrays nicht funktioniert:void foo(double *&bar);
ist die richtige Form.
quelle
Wenn Sie C ++ verwenden, ist der obligatorische Vorschlag, der hier noch fehlt, zu verwenden
std::vector<double>
.Sie können es leicht als Referenz übergeben:
void foo(std::vector<double>& bar) {}
Und wenn Sie C ++ 11-Unterstützung haben, schauen Sie sich auch an
std::array
.Als Referenz:
quelle
std::vector
ist normalerweise die beste Lösung. Es gibt jedoch Ausnahmen.8.3.5.8 Wenn der Typ eines Parameters einen Typ der Form "Zeiger auf Array mit unbekannter Grenze von T" oder "Verweis auf Array mit unbekannter Grenze von T" enthält, ist das Programm fehlerhaft
quelle
Wie die andere Antwort sagt, setzen Sie das
&
nach dem*
.Dies bringt einen interessanten Punkt hervor, der manchmal verwirrend sein kann: Typen sollten von rechts nach links gelesen werden. Dies ist beispielsweise (beginnend ganz rechts
*
) ein Zeiger auf einen konstanten Zeiger auf ein int.int * const *x;
Was Sie geschrieben haben, wäre daher ein Zeiger auf eine Referenz, was nicht möglich ist.
quelle
Hier erklärt Erik jede Art und Weise , wie ein Array durch Referenz übergeben wird : https://stackoverflow.com/a/5724184/5090928 .
Ebenso können Sie eine Array-Referenzvariable wie folgt erstellen :
int arr1[] = {1, 2, 3, 4, 5}; int(&arr2)[5] = arr1;
quelle