Ссылки (references). Ссылки на переменные, структуры, объединения и объекты классов. Отличия между ссылками и указателями. Примеры
Содержание
- 1. Как объявить ссылку на переменную? Общая форма. Символ &
- 2. Примеры объявления и использования ссылки на переменную, структуру, объединение
- 3. Какое отличие между ссылкой и указателем?
- 4. Как объявить ссылку на объект некоторого класса? Пример объявления и использования
- 5. Можно ли объявить ссылку на тип void? Существует ли тип void& ?
- 6. Можно ли изменить значение по ссылке, если оно объявлено с ключевым словом const (объявлено как константное)?
- 7. Как с помощью ссылки передать переменную или объект класса в функцию? Пример
- 8. Каким образом возвратить ссылку из функции? Примеры
- 9. Примеры инициализации структурной переменной с использованием ссылок
- 10. Какие существуют ограничения на работу со ссылками в C++?
- Связанные темы
Поиск на других ресурсах:
1. Как объявить ссылку на переменную? Общая форма. Символ &
Во время объявления, ссылка должна обязательно инициализироваться. В простейшем случае ссылки объявляется следующим образом:
type & ref_var = var;
где
- type – тип, на который объявляется ссылка;
- ref_var – переменная типа «ссылка» на type;
- var – переменная типа type, на которую объявляется ссылка.
2. Примеры объявления и использования ссылки на переменную, структуру, объединение
Пример 1. Объявление ссылки с именем rd на переменную целого типа d.
int d; // переменная int & rd = d; // ссылка с именем rd на переменную d, инициализируется при объявлении d = 0; rd = 2; // d = 2 /* int & rd2; // ошибка (ссылка должна быть инициализирована при объявлении) */
Пример 2. Объявление ссылки на структурную переменную.
Пусть задан тип структуры, которая описывает дату:
struct Date { int day; int month; int year; };
Тогда использование ссылки на структурную переменную типа Date может быть таким:
Date d; Date & rd = d; // ссылка на структуру Date // доступ к полям структуры по ссылке rd.day = 14; // d.day = 14 rd.month = 1; // d.month = 1 rd.year = 1972; // d.year = 1972
Пример 3. Объявление и использование ссылки на объединение
Пусть задано объединение TYPES:
union TYPES { int d[2]; char c[4]; float x; };
Демонстрация использования ссылки на об¢единение TYPES:
TYPES t; // t - переменная типа "объединение" TYPES & rt = t; // ссылка на t char c; int d; rt.c[0] = 'A'; c = t.c[0]; rt.d[1] = 28; d = t.d[1];
3. Какое отличие между ссылкой и указателем?
Между ссылкой и указателем можно выделить следующие основные отличия:
- при объявлении ссылка должна быть обязательно инициализирована. Указатель не обязательно инициализировать при объявлении. Указателю можно присваивать значения и после его объявления в процессе выполнения программы;
- после объявления ссылки и ее инициализации, этой ссылке нельзя присваивать адреса других объектов. Указатель может изменять свои значения сколько угодно;
- указателю можно присваивать нулевое значение при объявлении. Ссылке нельзя присваивать нулевое значение.
- при объявлении массива ссылок компилятор сообщит об ошибке. Объявлять массив указателей можно.
4. Как объявить ссылку на объект некоторого класса? Пример объявления и использования
Пусть задан класс CFloat. В классе объявляется внутренняя переменная типа float, конструкторы и методы доступа Get(), Set().
Пример демонстрирует использование ссылки на объект класса CFloat.
Программный код модуля, созданного по шаблону Win32 Console Application демонстрирующий использование ссылки на объект класса, имеет вид:
#include "stdafx.h" #include <iostream> using namespace std; class CFloat { float x; public: // конструкторы класса CFloat() { x = 0; } CFloat(float nx) { x = nx; } // методы доступа float Get() { return x; } void Set(float nx) { x = nx; } }; int _tmain(int argc, _TCHAR* argv[]) { // ссылка на объект класса CFloat CFloat f; // f - объект класса CFloat CFloat & rf = f; // rf - ссылка на объект класса CFloat float x; rf.Set(5.5); // доступ к методам класса по ссылке x = f.Get(); // x = 5.5 f.Set(-8.2); x = rf.Get(); // x = -8.2 return 0; }
5. Можно ли объявить ссылку на тип void? Существует ли тип void& ?
Нет.
6. Можно ли изменить значение по ссылке, если оно объявлено с ключевым словом const (объявлено как константное)?
Нет.
7. Как с помощью ссылки передать переменную или объект класса в функцию? Пример
С помощью ссылки можно передавать переменную или объект класса в функцию. Таким образом, в теле функции можно изменять значение переданной переменной.
Пример 1. Демонстрация передачи переменной типа int в функцию и изменения ее значения в теле функции. Приложение типа Win32 Console Application.
#include "stdafx.h" #include <iostream> using namespace std; // функция Inc5() - увеличивает на 5 void Inc5(int & t) // передача t по ссылке { t += 5; } int _tmain(int argc, _TCHAR* argv[]) { int d; d = 5; Inc5(d); // d = 10 Inc5(d); // d = 15 return 0; }
Пример 2. В примере демонстрируется передача объекта класса по ссылке. Пусть задан класс CRadius и функция Volume(). В функцию Volume() передается объект класса CRadius по ссылке.
Передача объекта класса по ссылке есть более эффективной в сравнении с передачей по значению. Так как при передаче объекта по значению все данные объекта копируются в стек. Если в объекте есть много данных, то это сильно увеличивает время выполнения при вызове функции.
Текст программы, созданной по шаблону Win32 Console Application:
#include "stdafx.h" #include <iostream> using namespace std; class CRadius { double radius; public: // конструкторы CRadius() { radius = 1; } CRadius(double nradius) { radius = nradius; } // методы доступа void Set(double nradius) { radius = nradius; } double Get() { return radius; } }; // вычисляет объем шара double Volume(CRadius & R) // передача по ссылке { double vol, radius; radius = R.Get(); vol = 4.0 / 3.0 * 3.1415 * radius * radius * radius; return vol; } int _tmain(int argc, _TCHAR* argv[]) { CRadius r(2.5); // экземпляр класса CRadius double vol; vol = Volume(r); // передача объекта класса по ссылке cout << vol << endl; // vol = 65.4479 return 0; }
8. Каким образом возвратить ссылку из функции? Примеры
Функция может возвращать ссылку на объект. В этом случае, вызов функции может размещаться в левой части оператора присваивания (см. пример 2).
Пример 1. Демонстрируется возвращение из функции ссылки на тип int.
#include "stdafx.h" #include <iostream> using namespace std; // возвращение ссылки из функции int & Inc5(int t) // функция увеличивает на 5 значение параметра t { t = t + 5; return t; } int _tmain(int argc, _TCHAR* argv[]) { int a, b; b = 7; a = Inc5(b); // a = 12 cout << a << endl; return 0; }
Пример 2. Демонстрируется изменение значения внешнего (глобального) массива A с помощью функции Change(), которая возвращает ссылку на элемент массива A с заданным индексом.
Текст демонстрационной программы, созданной по шаблону Win32 Console Application имеет следующий вид
#include "stdafx.h" #include <iostream> using namespace std; #define MAX 20 double A[MAX]; // функция, которая возвращает ссылку на элемент массива A с индексом index double & Change(int index) { // возвратить значение элемента массива A return A[index]; } int _tmain(int argc, _TCHAR* argv[]) { int i; // заполнение массива for (i=0; i<MAX; i++) A[i] = i * 2; // A = { 0.0, 2.0, 4.0, ..., 38.0 } // изменить значение элемента массива с индексом 5 с помощью функции ChangeA(5) = 3.25; // A[5] = 3.25; ChangeA(MAX-1) = -7.77; // A[19] = -7.77; return 0; }
9. Примеры инициализации структурной переменной с использованием ссылок
Показаны два способа инициализации структурной переменной.
Пример 1. Возврат ссылки на структурную переменную. Инициализация структурной переменной осуществляется в функции InitPixel().
#include "stdafx.h" #include <iostream> using namespace std; // структура пиксель struct Pixel { int x, y, color; }; // функция, которая возвращает ссылку на структуру Pixel & InitPixel(int value) { Pixel px; px.x = px.y = px.color = value; return px; } int _tmain(int argc, _TCHAR* argv[]) { Pixel px; Pixel px2 = InitPixel(5); // px2.x = 5; px2.y = 5; px2.color = 5; px = InitPixel(11); // px.x = 11; px.x = 11; px.x = 11; cout << px.x << " - " << px.y << " - " << px.color << endl; cout << px2.x << " - " << px2.y << " - " << px2.color << endl; return 0; }
Пример 2. Инициализация структурной переменной типа Pixel. Функция InitPixel() получает ссылку на структурную переменную в качестве параметра.
#include "stdafx.h" #include <iostream> using namespace std; // структура пиксель struct Pixel { int x, y, color; }; // функция, которая возвращает ссылку на структуру void InitPixel(Pixel & px, int x, int y, int color) { // изменение значения структурной переменной у функции px.x = x; px.y = y; px.color = color; return; } int _tmain(int argc, _TCHAR* argv[]) { Pixel px; Pixel px2; InitPixel(px, 3, 8, 10); // px.x = 3; px.y = 8; px.color = 11; InitPixel(px2, 5, 5, 8); // px2.x = 5; px2.y = 5; px2.color = 8; cout << px.x << " - " << px.y << " - " << px.color << endl; cout << px2.x << " - " << px2.y << " - " << px2.color << endl; return 0; }
10. Какие существуют ограничения на работу со ссылками в C++?
В языке C++ работа с оссылками имеет свои ограничения:
- ссылки не могут связываться с другими ссылками (только с переменными);
- не существует нулевой ссылки;
- ссылки должны быть инициализированы при их объявлении.