Referenzen in C++

Jinku Hu 12 Oktober 2023
  1. Verwenden Sie die Notation & attr(optional) declarator, um eine lvalue-Referenz in C++ zu deklarieren
  2. Verwenden von Referenzen zum Implementieren von Funktionsprototypen in C++
Referenzen in C++

In diesem Artikel werden die verschiedenen Methoden zum Verwenden von Verweisen in C++ veranschaulicht.

Verwenden Sie die Notation & attr(optional) declarator, um eine lvalue-Referenz in C++ zu deklarieren

Referenzen definieren alternative Namen für Objekte. Sie sind selbst keine Objekte, und folglich können wir keine Arrays von Referenzen oder Zeiger auf Referenzen haben. Referenzen beziehen sich nur auf bereits existierende Objekte, und sie sind an diese Objekte gebunden, was bedeutet, dass nach der Deklaration keine Änderung erlaubt ist.

Außerdem müssen Referenzen initialisiert werden, und wenn die Operation unter Verwendung der Referenznamen ausgeführt wird, werden die gebundenen Objekte modifiziert. Beachten Sie, dass die letztere Funktion sie den Zeigern sehr ähnlich macht. Wir können Referenzen als Alternativen zu Zeigern betrachten, außer dass erstere als reguläre Variablennamen ohne Dereferenzierungsnotation verwendet werden können, um auf den Wert des entsprechenden Objekts zuzugreifen. Wenn wir das Verhalten von Referenzen imitieren wollen, können wir einen const-Zeiger auf den angegebenen Typ deklarieren. Letztere zeichnet sich mit den gleichen Merkmalen wie Referenzen aus, mit Ausnahme der Schreibweise des Zugriffs auf die Werte.

Im folgenden Beispielcode wird die Variable xr als Referenz auf ein x deklariert, das ein int-Objekt repräsentiert. Sobald xr während der Deklaration initialisiert wurde, kann es nicht neu zugewiesen werden, um auf ein anderes Objekt jeglichen Typs zu verweisen. Andererseits können wir verschiedene Aliasnamen wie xr für dasselbe Objekt definieren, auf das es verweist. xrc ist nämlich eine const-qualifizierte Referenz, was bedeutet, dass auf den Wert des entsprechenden Objekts nur zugegriffen und nicht mit dem Aliasnamen geändert werden kann.

#include <iostream>

using std::cout;
using std::endl;

int main() {
  int x = 5;
  int& xr = x;
  const int& xrc = x;

  xr *= xr;
  //    xrc *= x; Error
  cout << "xr: " << xr << endl;
  cout << "xrc: " << xrc << endl;

  return EXIT_SUCCESS;
}

Ausgabe:

xr: 25
xrc: 25

Wir können mehrere Verweise auf dasselbe Objekt deklarieren, wie im folgenden Codeausschnitt gezeigt. Dennoch sollte man sich bewusst sein, dass sich Änderungen an einem der Aliasnamen auf dasselbe Objekt auswirken.

#include <iostream>

using std::cout;
using std::endl;

int main() {
  int x = 5;
  int& xr = x;
  int& xrr = x;

  xr *= xr;
  xrr *= xrr;
  cout << "xr: " << xr << endl;
  cout << "xrr: " << xrr << endl;

  return EXIT_SUCCESS;
}

Ausgabe:

xr: 625
xrr: 625

Verwenden von Referenzen zum Implementieren von Funktionsprototypen in C++

Referenzen werden hauptsächlich verwendet, um saubere Funktionsschnittstellen bereitzustellen, aber auch, weil die Sprache C++ Möglichkeiten zum Überladen von Operatoren bietet und die Notation für alle Operatoren gleich sein sollte. Letzteres wäre kompliziert, wenn es keine Referenzkonzepte in der Sprache gäbe. Die Verwendung der Operatoren, die Argumente als Zeiger verwenden müssen, hätte also wie ++&x aussehen können.

Funktionen, die Objekte für den Zugriff auf Werte benötigen, können die entsprechenden Argumente als const-Referenzen angeben und falls die Modifikation auch ohne const erforderlich ist. Zum Beispiel nimmt die Funktion printVector eine const-Referenz auf std::vector, um die Elemente in den cout-Stream zu drucken, aber swapElements muss jedes Element austauschen, also brauchen wir eine regelmäßige Referenz auf das Objekt.

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>

using std::cout;
using std::endl;
using std::setw;
using std::string;
using std::vector;

template <typename T>
void printVector(const vector<T> &vec) {
  for (auto &i : vec) {
    cout << i << "; ";
  }
  cout << endl;
}

template <typename T>
void swapElements(vector<T> &vec) {
  for (auto iter = vec.begin(); iter < vec.end() - 1; ++iter) {
    std::swap(*iter, *(iter + 1));
  }
}

int main() {
  vector<int> vec1 = {43, 5, 123, 94, 359, -23, 2, -1};

  printVector(vec1);
  swapElements(vec1);
  printVector(vec1);

  return EXIT_SUCCESS;
}

Ausgabe:

43; 5; 123; 94; 359; -23; 2; -1;
5; 123; 94; 359; -23; 2; -1; 43

Beachten Sie, dass alle vorherigen Referenzbeispiele, einschließlich der const-Referenzen, als Lvalue-Referenzen bezeichnet werden. Diese Referenzen werden verwendet, um auf die Objekte zu verweisen, die gültige Werte beibehalten müssen, nachdem wir darauf zugegriffen oder sie geändert haben. Die Sprache C++ stellt auch Rvalue-Referenzen bereit, die verwendet werden, um auf die temporären Objekte zu verweisen.

Ein temporäres Objekt ist eine Annahme für den Programmierer, dass das angegebene Objekt nicht wieder verwendet wird. Die Rvalue-Referenzen werden mit der Notation && attr(optional) declarator angegeben, und auf die Objekte wird wie auf die Lvalue-Referenzen zugegriffen. Rvalue-Referenzen werden verwendet, um effiziente Operationen zu implementieren, wie das Verschieben des Konstruktors und das Verschieben der Zuweisung, um teure Kopien großer Objekte zu vermeiden.

Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Verwandter Artikel - C++ Reference