Ссылки в C++
Ссылка в С++ — это альтернативное имя объекта.
Ссылку можно понимать как безопасный вариант указателя. При этом ссылки имеют особенности, отличающие их от указателей:
- При объявлении ссылка обязательно на уже существующий объект данного типа. Ссылка не может ссылаться «ни на что».
- Ссылка от её объявления до её исчезновения указывает на один и тот же адрес.
- При обращении к ссылке разыменование происходит автоматически.
- Адрес ссылки — это адрес исходного объекта, на который она указывает.
Объявление ссылок очень похоже на объявление указателей, только вместо звёздочки * пишется амперсанд &.
При объявлении ссылка обязана быть инициализирована.
int &x; // недопустимо!
int &x = veryLongVariableName; // допустимо. Теперь x — это альтернативное имя переменной veryLongVariableName
int A[10];
int &x = A[5]; // Ссылка может указывать на элемент массива
x++; // то же, что A[5]++;
x = 1; // то же, что A[5] = 1;
Передача параметров в функцию по ссылке
Параметры можно передавать по ссылкам. При этом связывание ссылки с определённой переменной произойдёт в момент вызова функции (на этапе выполнения программы).
void foo(int &x)
x = 3;
>
int main()
int t = 1;
foo (t);
cout >
Нужно быть осторожным при передаче значений в такую функцию стороннего разработчика.
Если не планируется изменение передаваемой переменной, функцию лучше объявить так:
void foo(const int &x);
Это гарантирует программисту-пользователю функции неизменность передаваемого значения.
Для типа int передача по константной ссылке обычно не нужна, так как можно просто передать аргумент по значению, но для большого класса или структуры передача по ссылке гораздо быстрее и экономит память.
Чего нельзя делать со ссылкой
Возврат из функции ссылки на автоматически созданный объект (локальную переменную) приводит к появлению «битых ссылок», значение которых непредсказуемо.
Также синтаксис С++ не позволяет создавать указатели на ссылки и массивы ссылок.
Передача ссылок на объекты
Когда объект передается функции как аргумент, создается копия объекта. Более того, при создании этой копии конструктор объекта не вызывается. Вместо этого делается точная копия объекта. Однако по окончании выполнения функции вызывается деструктор копии объекта. Если по каким-либо причинам нежелательно, чтобы создавалась копия объекта или чтобы вызывался деструктор, то надо передать объект в функцию по ссылке. При передаче по ссылке копия объекта не создается. Это также означает, что объект-параметр не будет уничтожаться при выходе из функции и соответственно не будет вызван деструктор. В качестве примера запустим следующую программу:
Программа выдает следующие результаты:
Constructing 1
-10
Destructing 1
Как можно видеть, деструктор объекта cl вызывался только один раз.
При передаче объекта в функцию по ссылке действие над объектом внутри функции модифицирует этот объект. И эти изменения сохраняют силу после завершения работы функции.
Практическое руководство. Создание связи с объектом или веб-страницей с помощью элемента управления LinkLabel в Windows Forms
Элемент управления Windows Forms LinkLabel позволяет создавать ссылки веб-типа в форме. После щелчка ссылки можно изменить ее цвет, чтобы указать, что по ссылке был выполнен переход. Дополнительные сведения об изменении цвета см. в статье Практическое руководство. Изменение внешнего вида элемента управления LinkLabel в Windows Forms.
Создание ссылки на другую форму
Создание ссылки на другую форму с помощью элемента управления LinkLabel
- Присвойте свойству Text соответствующую надпись.
- Задайте свойство LinkArea, чтобы определить, какая часть надписи будет указана в виде ссылки. Способ указания зависит от свойств, связанных с внешним видом метки ссылки. Значение LinkArea представлено объектом LinkArea, содержащим два числа — начальная позиция символа и количество символов. Свойство LinkArea можно задать в окне свойств или в коде следующим образом:
' In this code example, the link area has been set to begin ' at the first character and extend for eight characters. ' You may need to modify this based on the text entered in Step 1. LinkLabel1.LinkArea = New LinkArea(0, 8)
// In this code example, the link area has been set to begin // at the first character and extend for eight characters. // You may need to modify this based on the text entered in Step 1. linkLabel1.LinkArea = new LinkArea(0,8);
// In this code example, the link area has been set to begin // at the first character and extend for eight characters. // You may need to modify this based on the text entered in Step 1. linkLabel1->LinkArea = LinkArea(0,8);
Примечание. Экземпляр класса LinkLabelLinkClickedEventArgs содержит ссылку на элемент управления LinkLabel, который был нажат, поэтому выполнять приведение объекта sender не нужно.
Protected Sub LinkLabel1_LinkClicked(ByVal Sender As System.Object, _ ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) _ Handles LinkLabel1.LinkClicked ' Show another form. Dim f2 As New Form() f2.Show LinkLabel1.LinkVisited = True End Sub
protected void linkLabel1_LinkClicked(object sender, System. Windows.Forms.LinkLabelLinkClickedEventArgs e) < // Show another form. Form f2 = new Form(); f2.Show(); linkLabel1.LinkVisited = true; >
private: void linkLabel1_LinkClicked(System::Object ^ sender, System::Windows::Forms::LinkLabelLinkClickedEventArgs ^ e) < // Show another form. Form ^ f2 = new Form(); f2->Show(); linkLabel1->LinkVisited = true; >
Связывание с веб-страницей
Элемент управления LinkLabel можно также использовать для отображения веб-страницы в браузере по умолчанию.
Запуск Internet Explorer и создание ссылки на веб-страницу с помощью элемента управления LinkLabel
- Присвойте свойству Text соответствующую надпись.
- Задайте свойство LinkArea, чтобы определить, какая часть надписи будет указана в виде ссылки.
- В обработчике событий LinkClicked в середине блока обработки исключений вызовите вторую процедуру, которая задает свойству LinkVisited значение true и использует метод Start для запуска браузера по умолчанию с URL-адресом. Чтобы использовать метод Start, необходимо добавить ссылку на пространство имен System.Diagnostics.
Важно! Если приведенный ниже код выполняется в среде с частичным доверием (например, на общем диске), при вызове метода VisitLink JIT-компилятор завершится сбоем. Инструкция System.Diagnostics.Process.Start вызывает запрос ссылки, который завершается сбоем. Перехватывая исключение при вызове метода VisitLink , приведенный ниже код гарантирует, что в случае сбоя JIT-компилятора ошибка будет обработана корректно.
Private Sub LinkLabel1_LinkClicked(ByVal sender As System.Object, _ ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) _ Handles LinkLabel1.LinkClicked Try VisitLink() Catch ex As Exception ' The error message MessageBox.Show("Unable to open link that was clicked.") End Try End Sub Sub VisitLink() ' Change the color of the link text by setting LinkVisited ' to True. LinkLabel1.LinkVisited = True ' Call the Process.Start method to open the default browser ' with a URL: System.Diagnostics.Process.Start("http://www.microsoft.com") End Sub
private void linkLabel1_LinkClicked(object sender, System.Windows.Forms.LinkLabelLinkClickedEventArgs e) < try < VisitLink(); >catch (Exception ex ) < MessageBox.Show("Unable to open link that was clicked."); >> private void VisitLink() < // Change the color of the link text by setting LinkVisited // to true. linkLabel1.LinkVisited = true; //Call the Process.Start method to open the default browser //with a URL: System.Diagnostics.Process.Start("http://www.microsoft.com"); >
private: void linkLabel1_LinkClicked(System::Object ^ sender, System::Windows::Forms::LinkLabelLinkClickedEventArgs ^ e) < try < VisitLink(); >catch (Exception ^ ex) < MessageBox::Show("Unable to open link that was clicked."); >> private: void VisitLink() < // Change the color of the link text by setting LinkVisited // to true. linkLabel1->LinkVisited = true; // Call the Process.Start method to open the default browser // with a URL: System::Diagnostics::Process::Start("http://www.microsoft.com"); >
См. также
- Process.Start
- Общие сведения об элементе управления LinkLabel
- Практическое руководство. Изменение внешнего вида элемента управления LinkLabel в Windows Forms
- Элемент управления LinkLabel
Совместная работа с нами на GitHub
Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.
Указатели и ссылки в языке C++
Указатели представляют собой объекты, значением которых служат адреса других объектов:
- переменных
- констант
- функций
- других указателей
Объявление указателей
<тип> *<имя_переменной>[,*<имя_переменной>].
Синтаксис объявления указателей аналогичен объявлению переменных, за исключением того, что между типом данных и именем переменной должен быть указан символ «*» («звездочка»).
Инициализация указателей
Указателю можно присвоить адрес объекта, полученный с помощью оператора взятия адреса &. Стоит отметить, что оператор & не возвращает напрямую адрес своего операнда. Вместо этого он возвращает указатель, содержащий адрес.
Указателю нельзя присвоить адрес переменной другого типа. То есть нельзя указателю типа int* присвоить адрес переменной типа double.
Также указателю можно присвоить значение другого указателя.
Указатель также может быть проинициализирован пустым значением. Это можно сделать несколькими способами:
- использовать значение 0 или макроопределение NULL
- использовать значение nullptr
- использовать значение std::nullptr_t (C++ 11)
В некоторых случаях, использование значения 0 в качестве аргумента функции может привести к проблемам, так как компилятор не сможет определить, используется ли нулевой указатель или целое число. Поэтому использование значения nullptr является предпочтительным способом присвоить указателю пустое значение.
Тип std::nullptr_t может иметь только одно значение — nullptr. Использование этого типа поможет в тех редких случаях, когда существуют перегруженные функции и требуется передать нулевой указатель. В этом случае непонятно какую именно функцию нужно будет вызвать. Поэтому в таком случае в функции можно задать аргумент с типом std::nullptr_t.
Напрямую записать адрес в указатель можно только с помощью операций преобразования типов, либо операции reinterpret_cast.
int a = 0; int *p = &a; double v = 0.1; double *pv = &v; char *pc = nullptr;
Разыменование указателей
Для получения значения переменной, на которую ссылается указатель, используется операция разыменования указателя. Эта операция записывается как символ * (звездочка), написанный перед указателем.
int a = 123; int *p = &a; int b = *p; // b присваивается значение 123
Арифметические действия с указателями
С указателем можно производить следующие арифметические действия:
- сложение и вычитание с целым числом
- операции инкремента/декремента
При использовании арифметических операций, указатель изменяется на величину кратную размеру типа указателя. Например, если указатель имеет тип 32-разрядного int, то увеличение указателя на 1 приведет к увеличению значения адреса в указателе на 4.
Указатель на указатель
В языке C++ можно объявить указатель, который будет указывать на другой указатель.
Синтаксис объявления такой же, как и у объявления указателя, за исключением того, что ставится два символа * (звездочка).
<тип> **<имя_переменной>[,**<имя_переменной>].
Указатель на указатель работает подобно обычному указателю: его можно разыменовать для получения значения, на которое он указывает. И, поскольку этим значением является другой указатель, для получения исходного значения потребуется выполнить разыменование еще раз. Разыменования можно выполнять последовательно:
int value = 1234; int *p = &value; int **pp = &p; int val = **pp; // 1234
Использовать указатели на указатели может потребоваться, например для создания массива из массивов, и в частности массива из строк.
Язык C++ также позволяет работать с указателями на указатели на указатели, или сделать еще большую вложенность. Их можно объявлять просто увеличивая количество символов * (звездочек). Однако на практике такие указатели используются крайне редко.
Неконстантный указатель на неконстантное значение
int val1 = 10; int val2 = 20; int* ptr = &val1; std::coutВ этом случае можно изменять как сам указатель, так и значение, на которое он указывает.
Неконстантный указатель на константное значение
const int val1 = 10; const int val2 = 20; const int* ptr = &val1; std::coutВ этом случае указатель можно изменять. Но само значение, на которое он указывает изменять нельзя.
То же самое поведение можно получить, даже если переменные указаны как неконстантные. Для этого достаточно сам указатель объявить таким образом, чтобы он якобы указывал на константное значение:
int val1 = 10; int val2 = 20; const int* ptr = &val1; std::coutКонстантный указатель на неконстантное значение
int val1 = 10; int val2 = 20; int* const ptr = &val1; std::coutВ этом случае можно изменять значение, на которое указывает указатель. Но нельзя изменять сам указатель.
Кроме того указатель при объявлении нужно сразу инициализировать.
Константный указатель на константное значение
int val1 = 10; int val2 = 20; const int* const ptr = &val1; std::coutВ этом случае нельзя менять ни указатель, ни значение, на которое он указывает.
Ссылки
Ссылка - это тип переменной в языке C++, который работает как псевдоним другого объекта или значения. При объявлении ссылки перед её именем ставится символ амперсанда &. Сама же ссылка не может быть пустой, и должна быть обязательно проинициализирована именем переменной, на которую она ссылается. Изменить значение ссылки после инициализации невозможно.
<тип> &<имя_ссылки> = <имя_переменной>[, &<имя_ссылки> = <имя_переменной>].
При создании ссылки на константную переменную, ссылка тоже должна быть создана как константная. Можно также создать константную ссылку на обычную переменную: в этом случае изменить переменную через ссылку не получится.
Любые действия со ссылкой трактуются компилятором как действия, которые будут выполняться над объектом, на который она ссылается.
Ссылки чаще всего используются в качестве параметров в функциях. В этом контексте ссылка-параметр работает как псевдоним аргумента, а сам аргумент не копируется при передаче в параметр. Это в свою очередь улучшает производительность, если аргумент слишком большой или затратный для копирования.
Также ссылка может использоваться и при возврате значений из функции, однако тут следует быть осторожным, так как, если переменная, на которую ссылается ссылка, выйдет из области видимости (например локальная переменная в функции), то это приведет к неопределенному поведению программы.
int value = 123; int &refval = value; refval = 12345; std::coutСсылки r-value
В стандарте C++11 ввели новый тип ссылок - ссылки r-value. Ссылки r-value - это ссылки, которые инициализируются только значениями r-values. Объявляются такие ссылки, в отличие от обычных, с помощью двух символов амперсанда &&.
<тип> &&<имя_ссылки> = <выражение r-value>[, &&<имя_ссылки> = <выражение r-value>].
Ссылки r-value, в отличие от обычных ссылок, ссылаются не на постоянный, а на временный объект, созданный при инициализации ссылки r-value.
Такие ссылки обладают двумя важными свойствами:
- продолжительность жизни объекта, на который ссылается ссылка увеличивается до продолжительности жизни самой ссылки
- неконстантные ссылки r-value позволяют менять значение r-values, на который они ссылаются
int &&ref = 10; ref = ref + 20; std::coutСсылки r-value - позволяют избегать логически ненужного копирования и обеспечивать возможность идеальной передачи (perfect forwarding). Прежде всего они предназначены для использования в высокопроизводительных проектах и библиотеках.
- Уголок в Вконтакте
- Уголок в Телеграм
- Уголок в YouTube
- Все справочники
- Справочник по JavaScript
- Справочник по Ассемблеру
- Справочник по C++
- - Типы данных
- - Переменные
- - Указатели и ссылки
- - Массивы
- - Циклы и ветвления
- - Перечисления
- - Структуры и объединения
- - Классы
- - Наследование классов
- - Перегрузка операторов