Werden Vektoren in C ++ als Wert oder als Referenz an Funktionen übergeben?

92

Ich codiere in C ++. Wenn ich eine Funktion habevoid foo(vector<int> test) und sie in meinem Programm aufrufe, wird der Vektor dann als Wert oder Referenz übergeben? Ich bin mir nicht sicher, weil ich weiß, dass Vektoren und Arrays ähnlich sind und dass eine Funktion wie void bar(int test[])der Test den Test als Referenz (Zeiger?) Statt als Wert bestehen würde. Ich vermute, dass ich den Vektor explizit als Zeiger / Referenz übergeben müsste, wenn ich vermeiden möchte, dass ein Wert übergeben wird, aber ich bin mir nicht sicher.

Adam
quelle
5
C ++ hat die Semantik "Wert übergeben", daher wird sie als Wert übergeben. Sie können sich jedoch dafür entscheiden, als Referenz zu übergeben. Die Wahl hängt wirklich davon ab, was die Funktion tut.
Juanchopanza
2
Verwenden Sie als Referenz. Wenn die Funktion den Vektorinhalt nicht ändern soll, machen Sie sie konstant. Andernfalls übergeben Sie sie einfach als Referenz. Es wird unerwünschte und kostspielige (manchmal) Kopien vermeiden
Ali Kazmi
3
Eine Referenz ist auch kein Zeiger.
Das paramagnetische Croissant
2
@AliKazmi Außer wenn Sie eine Kopie im Hauptteil der Funktion wünschen.
Juanchopanza
Es kommt darauf an, was Sie erreichen wollen. Die Verwendung eines der Standard-Smart-Zeiger ist manchmal nützlich. Wenn Sie beispielsweise den Besitz weitergeben möchten, verwenden Sie unique_ptr. Aber normalerweise übergebe ich std :: vector als Referenz.
Erik Alapää

Antworten:

130

Wenn ich raten müsste, würde ich sagen, dass Sie einen Java-Hintergrund haben. Dies ist C ++, und die Dinge werden als Wert übergeben, sofern Sie mit dem &Operator -operator nichts anderes angeben (beachten Sie, dass dieser Operator auch als Operator "Adresse von" verwendet wird, jedoch in einem anderen Kontext). Dies ist alles gut dokumentiert, aber ich werde es trotzdem wiederholen:

void foo(vector<int> bar); // by value
void foo(vector<int> &bar); // by reference (non-const, so modifiable inside foo)
void foo(vector<int> const &bar); // by const-reference

Sie können auch einen Zeiger auf einen Vektor übergeben (void foo(vector<int> *bar) ) übergeben. Wenn Sie jedoch nicht wissen, was Sie tun, und das Gefühl haben, dass dies wirklich der richtige Weg ist, tun Sie dies nicht.

Vektoren sind es auch nicht dasselbe wie Arrays! Intern verfolgt der Vektor ein Array, von dem er die Speicherverwaltung für Sie übernimmt, aber auch viele andere STL-Container. Sie können einen Vektor nicht an eine Funktion übergeben, die einen Zeiger oder ein Array erwartet, oder umgekehrt (Sie können jedoch auf das zugrunde liegende Array zugreifen (auf dieses zeigen) und dies verwenden). Vektoren sind Klassen, die durch ihre Elementfunktionen viel Funktionalität bieten, während Zeiger und Arrays integrierte Typen sind. Außerdem werden Vektoren dynamisch zugewiesen (was bedeutet, dass die Größe zur Laufzeit bestimmt und geändert werden kann), während die Arrays im C-Stil statisch zugewiesen werden (ihre Größe ist konstant und muss zur Kompilierungszeit bekannt sein), was ihre Verwendung einschränkt.

Ich schlage vor, Sie lesen etwas mehr über C ++ im Allgemeinen (insbesondere Array-Zerfall ) und schauen sich dann das folgende Programm an, das den Unterschied zwischen Arrays und Zeigern veranschaulicht:

void foo1(int *arr) { cout << sizeof(arr) << '\n'; }
void foo2(int arr[]) { cout << sizeof(arr) << '\n'; }
void foo3(int arr[10]) { cout << sizeof(arr) << '\n'; }
void foo4(int (&arr)[10]) { cout << sizeof(arr) << '\n'; }

int main()
{
    int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    foo1(arr);
    foo2(arr);
    foo3(arr);
    foo4(arr);
}
JorenHeit
quelle
2
Kann mir jemand helfen, die letzte Deklaration der Funktion foo4 zu verstehen? Warum wird die Größe des Arrays anstelle der Größe des Zeigers wie in anderen Funktionen zurückgegeben?
Abhishek_M
3
@abhishek_M, da der Parametertyp eine Referenz ist. Eine Referenz kann nur an einen Ausdruck des exakt gleichen Typs gebunden werden. Aus diesem Grund zerfällt das Array nicht, da ein Verweis auf ein Array nicht an einen Zeiger gebunden werden kann, sondern nur an ein Array des gleichen Typs (in diesem Fall ein Array mit 10 Ganzzahlen)
bolov
c ++ 11 hat "Verschiebungssemantik" und Sie können dies sorgfältig tun und den Wert (mit Verschiebungssemantik) ohne Kopie übergeben. Hier ist ein Link, der mir sehr geholfen hat: mbevin.wordpress.com/2012/11/20/move-semantics
fchen
20

A vectorist funktional identisch mit einem Array. Aber für die Sprache vectorist ein Typ und intist auch ein Typ. Für ein Funktionsargument wird ein Array eines beliebigen Typs (einschließlich vector[]) als Zeiger behandelt. A vector<int>ist nicht dasselbe wie int[](für den Compiler). vector<int>ist kein Array, keine Referenz und kein Zeiger - es wird als Wert übergeben und ruft daher den Kopierkonstruktor auf.

Sie müssen es also verwenden vector<int>&(vorzugsweise mit const, wenn die Funktion es nicht ändert), um es als Referenz zu übergeben.

Ajay
quelle
Wie lautet die Syntax zum Übergeben eines "Arrays von Vektoren" unter Bezugnahme auf eine Funktion?
ab123
void functionName (std :: vector <int> (& vc) [5]) {}
RIanGillis
9

void foo(vector<int> test)

Der Vektor würde dabei als Wert übergeben.

Sie haben je nach Kontext mehr Möglichkeiten, Vektoren zu übergeben: -

1) Als Referenz übergeben: - Dadurch kann die Funktion foo Ihren Inhalt des Vektors ändern. Effizienter als die Übergabe von Werten, da das Kopieren von Vektoren vermieden wird.

2) Übergeben von const-reference: - Dies ist sowohl effizient als auch zuverlässig, wenn die Funktion den Inhalt des Vektors nicht ändern soll.

Ravi
quelle
1

Wenn wir Vektor als Wert in einer Funktion als Argument übergeben, wird einfach die Kopie des Vektors erstellt, und es tritt keine Auswirkung auf den Vektor auf, der in der Hauptfunktion definiert ist, wenn wir diese bestimmte Funktion aufrufen. Wenn wir den Vektor als Referenz übergeben, was auch immer in dieser bestimmten Funktion geschrieben ist, wird jede Aktion für den Vektor ausgeführt, der in der Haupt- oder anderen Funktion definiert ist, wenn wir diese bestimmte Funktion aufrufen.

Nishant Yadav
quelle