void DoWork(int n);
void DoWork(const int &n);
Was ist der Unterschied?
Pirat für Profit
void DoWork(int n);
void DoWork(const int &n);
Was ist der Unterschied?
CB Bailey
Der wichtige Unterschied ist, dass beim Vorbeigehen const
Referenz wird kein neues Objekt erstellt. Im Funktionsrumpf ist der Parameter effektiv ein Alias für das übergebene Objekt.
Denn die Referenz ist a const
Der Verweis auf den Funktionskörper kann den Wert dieses Objekts nicht direkt ändern. Dies hat eine ähnliche Eigenschaft wie die Wertübergabe, bei der der Funktionskörper den Wert des übergebenen Objekts ebenfalls nicht ändern kann, da der Parameter in diesem Fall eine Kopie ist.
Es gibt entscheidende Unterschiede. Wenn der Parameter a const
Referenz, aber das übergebene Objekt war es tatsächlich nicht const
dann kann der Wert des Objekts während des Funktionsaufrufs selbst geändert werden.
Z.B
int a;
void DoWork(const int &n)
{
a = n * 2; // If n was a reference to a, n will have been doubled
f(); // Might change the value of whatever n refers to
}
int main()
{
DoWork(a);
}
Auch wenn das übergebene Objekt eigentlich nicht war const
dann könnte die Funktion (auch wenn es schlecht beraten ist) ihren Wert mit einem Cast ändern.
z.B
void DoWork(const int &n)
{
const_cast<int&>(n) = 22;
}
Dies würde zu undefiniertem Verhalten führen, wenn das übergebene Objekt tatsächlich vorhanden wäre const
.
Wenn der Parameter per const-Referenz übergeben wird, entstehen zusätzliche Kosten durch Dereferenzierung, schlechtere Objektlokalität und weniger Möglichkeiten zur Optimierung der Kompilierung.
Wenn der Parameter als Wert übergeben wird, entstehen zusätzliche Kosten durch die Notwendigkeit, eine Parameterkopie zu erstellen. Dies ist normalerweise nur von Bedeutung, wenn der Objekttyp groß ist.
Könnten Sie bitte erklären, was die Strafe ist, wenn Sie erwähnen schlechtere Objektlokalität in deiner antwort?
– Zoso
1. März 2021 um 20:43 Uhr
Wahrscheinlich en.wikipedia.org/wiki/Locality_of_reference. TLDR Wenn häufig aufgerufene Teile des Speichers gruppiert werden, können Sie durch das Caching von Interna eine bessere Leistung erzielen. Eine andere Möglichkeit, dies zu beeinflussen, sind GCC-Attribute hot
und cold
.
– Benutzer4945014
9. Juni 2021 um 4:17 Uhr
Warum führt das Übergeben von const-Referenzen zu schlechtere Objektlokalität?
– rohitjv
9. Oktober 2021 um 18:00 Uhr
@rohitjv das referenzierte Objekt kann irgendwo im Speicher liegen. Wenn Sie als Wert übergeben, haben Sie das gesamte Objekt (eine Kopie) direkt in Ihrem aktuellen Stapelrahmen, dh in der Speicherregion, in der Ihre Funktion “lebt”, die as ist lokal wie es kommt.
– Reizo
20. März um 0:28 Uhr
Afriza N. Arief
Der Unterschied ist deutlicher, wenn Sie eine große Struktur/Klasse übergeben:
struct MyData {
int a,b,c,d,e,f,g,h;
long array[1234];
};
void DoWork(MyData md);
void DoWork(const MyData& md);
Wenn Sie den “normalen” Parameter verwenden, übergeben Sie den Parameter als Wert und erstellen somit eine Kopie des übergebenen Parameters. Wenn Sie const reference verwenden, übergeben Sie es als Referenz und die Originaldaten werden nicht kopiert.
In beiden Fällen können die Originaldaten nicht innerhalb der Funktion geändert werden.
BEARBEITEN:
In bestimmten Fällen können die Originaldaten möglicherweise geändert werden, wie Charles Bailey in seiner Antwort darauf hingewiesen hat.
Erfordert das Passieren von ref const
? Ich meine, würde Ihre Antwort nicht für den Fall gelten, in dem wir nur “normale” Parameter mit Ref-Parametern verglichen haben?
– Gonidelis
31. Januar 2021 um 15:46 Uhr
Das Passieren von ref ist nicht erforderlich const
natürlich.. es ist nur das durch haben const
hilft Ihnen der Compiler, die Änderung der Originaldaten zu vermeiden. Dies kann jedoch absichtlich umgangen werden, wie von Charles Bailey hervorgehoben.
– Afriza N. Arief
1. Februar 2021 um 3:39 Uhr
sneha
Es gibt drei Methoden, mit denen Sie Werte in der Funktion übergeben können
Wert übergeben
void f(int n){
n = n + 10;
}
int main(){
int x = 3;
f(x);
cout << x << endl;
}
Ausgang: 3. Nachteil: Wenn Parameter x
durchlaufen f
Funktion dann erstellt der Compiler eine Kopie im Speicher in von x. Also Speicherverschwendung.
Als Referenz übergeben
void f(int& n){
n = n + 10;
}
int main(){
int x = 3;
f(x);
cout << x << endl;
}
Ausgang: 13. Es eliminiert den Nachteil der Wertübergabe, aber wenn der Programmierer den Wert nicht ändern möchte, dann verwenden Sie eine konstante Referenz
Konstante Referenz
void f(const int& n){
n = n + 10; // Error: assignment of read-only reference ‘n’
}
int main(){
int x = 3;
f(x);
cout << x << endl;
}
Ausgabe: Fehler anwerfen n = n + 10
denn wenn wir das const-Referenzparameterargument übergeben, dann ist es ein schreibgeschützter Parameter, Sie können den Wert von n nicht ändern.
Wollen Sie die print-Anweisung in main() haben, nachdem f() aufgerufen wurde? Denn mit der print-Anweisung in f() ist die Ausgabe des ersten Beispiels meiner Meinung nach falsch: Es sollte 13 sein, oder?
– Seb
20. April 2017 um 18:21 Uhr
Nein @Seb du hast nicht Recht. Die Ausgabe wird 3 selbst sein. Das bedeutet es Wert übergeben. Das Wert von x
übergeben wird, nämlich 3
und nicht x
selbst. Worüber Sie sprechen, ist Pass by Reference, dh das 2. Beispiel …
– Sabito 錆兎 steht zur Ukraine
2. August 2020 um 5:48 Uhr
Hm. Ja, scheint jetzt richtig zu sein. Mein Kommentar ist über 3 Jahre her. Vielleicht wurde es bearbeitet? (Wenn nicht, tut es mir leid. (: )
– Seb
3. August 2020 um 12:57 Uhr
Mit
void DoWork(int n);
n
ist eine Kopie des Werts des tatsächlichen Parameters, und es ist zulässig, den Wert von zu ändern n
innerhalb der Funktion. Mit
void DoWork(const int &n);
n
ist ein Verweis auf den tatsächlichen Parameter, und es ist nicht zulässig, seinen Wert zu ändern.
Da keiner von euch etwas über das Schlüsselwort const erwähnt hat …
Das konst Schlüsselwort ändert den Typ einer Typdeklaration oder den Typ eines Funktionsparameters und verhindert, dass der Wert variiert. (Quelle: MS)
Mit anderen Worten: Das Übergeben eines Parameters als Referenz macht ihn der Änderung durch den Aufgerufenen ausgesetzt. Verwendung der konst Schlüsselwort verhindert die Änderung.
Andreas Brink
Die erste Methode wird bestanden n
nach Wert, dh eine Kopie von n
wird an die Funktion gesendet. Der zweite geht vorbei n
per Referenz, was im Grunde bedeutet, dass ein Zeiger auf die n
mit der die Funktion aufgerufen wird, an die Funktion gesendet.
Für ganzzahlige Typen wie int
Es macht nicht viel Sinn, als konstante Referenz zu übergeben, da die Größe der Referenz normalerweise mit der Größe der Referenz (des Zeigers) identisch ist. In den Fällen, in denen das Erstellen einer Kopie teuer ist, ist es normalerweise am besten, die const-Referenz zu verwenden.
Winter
Erstens gibt es kein Konzept für Lebenslauf-qualifizierte Zeugnisse. Daher ist die Terminologie „const reference“ nicht korrekt und wird normalerweise verwendet, um „Referenz auf const“ zu beschreiben. Es ist besser, darüber zu sprechen, was gemeint ist.
$8.3.2/1- “Lebenslauf-qualifizierte Verweise sind falsch formatiert, außer wenn die Lebenslauf-Qualifizierer durch die Verwendung einer Typedef (7.1.3) oder eines Template-Typ-Arguments (14.3) eingeführt werden, in diesem Fall ist der Lebenslauf- Qualifizierer werden ignoriert.”
Hier sind die Unterschiede
$13.1 – “Nur die const- und volatile-Typspezifizierer auf der äußersten Ebene der Parametertypspezifikation werden auf diese Weise ignoriert; const- und volatile-Typspezifizierer, die in einer Parametertypspezifikation verborgen sind, sind signifikant und können verwendet werden, um überladene Funktionsdeklarationen zu unterscheiden. 112) Insbesondere werden für jeden Typ T „Zeiger auf T“, „Zeiger auf Konstante T“ und „Zeiger auf flüchtiges T“ als unterschiedliche Parametertypen angesehen, ebenso wie „Verweis auf T“, „Verweis auf Konstante T“. “ und „Verweis auf flüchtiges T.“
void f(int &n){
cout << 1;
n++;
}
void f(int const &n){
cout << 2;
//n++; // Error!, Non modifiable lvalue
}
int main(){
int x = 2;
f(x); // Calls overload 1, after the call x is 3
f(2); // Calls overload 2
f(2.2); // Calls overload 2, a temporary of double is created $8.5/3
}