Riferimenti in C++

Jinku Hu 12 ottobre 2023
  1. Usa la notazione & attr(optional) declarator per dichiarare un riferimento lvalue in C++
  2. Usa riferimenti per implementare prototipi di funzioni in C++
Riferimenti in C++

Questo articolo illustra i più metodi di come utilizzare i riferimenti in C++.

Usa la notazione & attr(optional) declarator per dichiarare un riferimento lvalue in C++

I riferimenti definiscono nomi alternativi per gli oggetti. Non sono oggetti stessi e, di conseguenza, non possiamo avere array di riferimenti o puntatori a riferimenti. I riferimenti si riferiscono solo a oggetti già esistenti e sono legati a questi oggetti, il che implica che non è consentita alcuna modifica dopo la dichiarazione.

Inoltre, i riferimenti devono essere inizializzati e quando l’operazione viene eseguita utilizzando i nomi dei riferimenti, gli oggetti associati vengono modificati. Si noti che quest’ultima caratteristica li rende abbastanza simili ai puntatori. Possiamo considerare i riferimenti come alternative ai puntatori, tranne per il fatto che i primi possono essere usati come nomi di variabili regolari senza una notazione di dereferenziazione per accedere al valore dell’oggetto corrispondente. Se vogliamo imitare il comportamento dei riferimenti, possiamo dichiarare un puntatore const al tipo dato. Quest’ultimo si caratterizza con le stesse caratteristiche dei riferimenti fatta eccezione per la notazione di accesso ai valori.

Nel codice di esempio seguente, la variabile xr è dichiarata come riferimento a una x, che rappresenta un oggetto int. Una volta inizializzato xr durante la dichiarazione, non può essere riassegnato per fare riferimento a un oggetto diverso di qualsiasi tipo. D’altra parte, possiamo definire diversi nomi di alias come xr allo stesso oggetto a cui si riferisce. Vale a dire, xrc è un riferimento qualificato const, il che significa che è possibile accedere solo al valore dell’oggetto corrispondente e non può essere modificato utilizzando il nome alias.

#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;
}

Produzione:

xr : 25 xrc : 25

Possiamo dichiarare più riferimenti allo stesso oggetto, come dimostrato nel seguente frammento di codice. Tuttavia, si dovrebbe essere consapevoli che le modifiche da uno qualsiasi degli alias influenzeranno lo stesso oggetto.

#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;
}

Produzione:

xr : 625 xrr : 625

Usa riferimenti per implementare prototipi di funzioni in C++

I riferimenti sono utilizzati principalmente per fornire interfacce di funzioni più pulite, ma anche perché il linguaggio C++ fornisce capacità di sovraccarico degli operatori e la notazione dovrebbe essere la stessa per tutti gli operatori. Quest’ultimo sarebbe complicato se non ci fossero concetti di riferimento nella lingua. Pertanto, l’utilizzo degli operatori che devono prendere argomenti come puntatori potrebbe avere l’aspetto di ++&x.

Le funzioni che devono prendere oggetti per accedere ai valori possono specificare gli argomenti corrispondenti come riferimenti const e se la modifica è richiesta anche senza const. Ad esempio, la funzione printVector prende un riferimento const a std::vector per stampare gli elementi nel flusso cout, ma swapElements deve scambiare ogni elemento, quindi dobbiamo avere un riferimento regolare a l’oggetto.

#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;
}

Produzione:

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

Nota che tutti gli esempi precedenti di riferimenti, inclusi quelli const, sono chiamati riferimenti lvalue. Questi riferimenti sono usati per fare riferimento agli oggetti che devono conservare valori validi dopo che li abbiamo accessi o modificati. Il linguaggio C++ fornisce anche riferimenti rvalue, che vengono utilizzati per fare riferimento agli oggetti temporanei.

Un oggetto temporaneo è un presupposto per il programmatore che l’oggetto dato non verrà utilizzato di nuovo. I riferimenti rvalue sono specificati usando la notazione && attr(optional) declarator e si accede agli oggetti come i riferimenti lvalue. I riferimenti Rvalue vengono utilizzati per implementare operazioni efficienti, come spostare il costruttore e spostare l’assegnazione per evitare copie costose di oggetti di grandi dimensioni.

Autore: 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