Referencias en C++

Jinku Hu 12 octubre 2023
  1. Utilice la notación & attr(optional) declarator para declarar una referencia lvalue en C++
  2. Utilice referencias para implementar prototipos de funciones en C++
Referencias en C++

Este artículo muestra los múltiples métodos de cómo utilizar referencias en C++.

Utilice la notación & attr(optional) declarator para declarar una referencia lvalue en C++

Las referencias definen nombres alternativos para los objetos. No son objetos en sí mismos, y en consecuencia, no podemos tener matrices de referencias o punteros a referencias. Las referencias solo se refieren a objetos ya existentes y están vinculados a estos objetos, lo que implica que no se permiten modificaciones después de la declaración.

Además, las referencias deben inicializarse, y cuando la operación se realiza utilizando los nombres de referencia, los objetos vinculados se modifican. Tenga en cuenta que esta última característica los hace bastante similares a los punteros. Podemos considerar las referencias como alternativas a los punteros, excepto que los primeros pueden usarse como nombres de variables regulares sin una notación de desreferenciación para acceder al valor del objeto correspondiente. Si queremos imitar el comportamiento de las referencias, podemos declarar un puntero const al tipo dado. Este último se caracteriza por tener las mismas características que las referencias excepto por la notación de acceso a los valores.

En el siguiente código de ejemplo, la variable xr se declara como referencia a un x, que representa un objeto int. Una vez que se inicializa xr durante la declaración, no se puede reasignar para hacer referencia a un objeto diferente de ningún tipo. Por otro lado, podemos definir diferentes nombres de alias como xr para el mismo objeto al que se refiere. Es decir, xrc es una referencia calificada const, lo que significa que solo se puede acceder al valor del objeto correspondiente y no se puede modificar mediante el nombre de 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;
}

Producción :

xr: 25
xrc: 25

Podemos declarar múltiples referencias al mismo objeto, como se demuestra en el siguiente fragmento de código. Aún así, uno debe tener en cuenta que las modificaciones de cualquiera de los alias afectarán al mismo objeto.

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

Producción :

xr: 625
xrr: 625

Utilice referencias para implementar prototipos de funciones en C++

Las referencias se utilizan principalmente para proporcionar interfaces de funciones más limpias, pero también porque el lenguaje C++ proporciona capacidades de sobrecarga de operadores, y la notación debe ser la misma para todos los operadores. Esto último sería complicado si no hubiera conceptos de referencia en el idioma. Por lo tanto, el uso de operadores que necesitan tomar argumentos como punteros podría haber parecido ++&x.

Las funciones que necesitan tomar objetos para acceder a valores pueden especificar los argumentos correspondientes como referencias const y si la modificación también es necesaria sin const. Por ejemplo, la función printVector toma una referencia const a std::vector para imprimir los elementos al flujo cout, pero swapElements necesita intercambiar cada elemento, por lo que necesitamos tener una referencia regular al objeto.

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

Producción :

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

Tenga en cuenta que todos los ejemplos anteriores de referencias, incluidos los const, se denominan referencias de valor l. Estas referencias se utilizan para hacer referencia a los objetos que necesitan conservar valores válidos después de acceder a ellos o modificarlos. El lenguaje C++ también proporciona referencias rvalue, que se utilizan para hacer referencia a los objetos temporales.

Un objeto temporal es una suposición para el programador de que el objeto dado no se volverá a utilizar. Las referencias rvalue se especifican usando la notación && attr(optional) declarator, y se accede a los objetos como las referencias lvalue. Las referencias de Rvalue se utilizan para implementar operaciones eficientes, como mover el constructor y mover la asignación para evitar copias costosas de objetos grandes.

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

Artículo relacionado - C++ Reference