Was ist der Unterschied zwischen einer konstanten Referenz und einem normalen Parameter?

Lesezeit: 6 Minuten

Benutzer-Avatar
Pirat für Profit

void DoWork(int n);
void DoWork(const int &n);

Was ist der Unterschied?

Benutzer-Avatar
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

Benutzer-Avatar
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 consthilft 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

Benutzer-Avatar
sneha

Es gibt drei Methoden, mit denen Sie Werte in der Funktion übergeben können

  1. 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.

  2. 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

  3. 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.

Benutzer-Avatar
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.

Benutzer-Avatar
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
}

1013090cookie-checkWas ist der Unterschied zwischen einer konstanten Referenz und einem normalen Parameter?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy