Что такое определение ссылочного типа?
Как вы определяете (объясняете) формально и строго, что такое ссылочный тип в C++?
Я попытался гуглить и заглянул в Страуструпа "Язык программирования C++", но не вижу там определения этого понятия.
3 ответа
Ссылка - это псевдоним, альтернативное имя для объекта. Это не сам объект (и, таким образом, не указатель, даже если некоторые из их использования перекрываются с использованием указателей).
Ссылки имеют определенные ограничения на обработку, связанные с их необъективностью. Например, вы не можете создать массив ссылок. Они должны быть инициализированы (связаны, размещены), как только они объявлены, поскольку они не могут существовать без объекта с псевдонимом.
Однако вы можете хранить их, и они подчиняются правилам автоматических переменных или переменных-членов. Одно из их применений состоит в том, чтобы пробираться через вызовы функции передачи по значению в C++.
Обратите внимание, что константные ссылки имеют аккуратный побочный эффект того, что они являются псевдонимами: когда они связаны с временным (то есть неназванным) объектом, они дают указанному объекту имя и, следовательно, продлевают его время жизни до самой ссылки.
{ // Block scope
Foo fooVal = makeFoo(); // Say makeFoo() returns a (temporary, unnamed) Foo
// Here the temporary Foo is dead (fooVal is a copy).
// Foo &fooRef = makeFoo(); // Error, reference is non-const
Foo const &fooCRef = makeFoo(); // All good
// ...
// The second temporary is still alive
fooCRef.doSomethingFunny(); // Works like a charm !
} // The second temporary dies with fooRef
Остерегайтесь, однако, возможно (хотя и придумано) вывести объект из области видимости, ссылаясь на него. Тогда у вас будут свисающие ссылки, которые больше не будут использоваться (это будет неопределенным поведением).
Foo *fooPtr = new Foo; // Here is a Foo
Foo &fooRef = *fooPtr; // Here is an alias for that Foo
delete fooPtr; // Here is the end of that Foo's life
fooRef.doSomethingFunny(); // Here comes trouble...
Относительно
Как вы определяете (объясняете) формальным и строгим образом, что такое ссылочный тип в C++?
стандарт C++11 дает следующее формальное и строгое определение ссылочного типа в его
§8.3.2/1
В декларации T D, где D имеет одну из форм
&
атрибут-спецификатор-seq оптD1
&&
атрибут-спецификатор-seq оптD1
и тип идентификатора в объявленииT D1
такое " производный-декларатор-тип-список"T
, Затем тип идентификатораD
является " производной-декларатор- ссылка на список типовT
".
Однако, если вас больше интересует, что такое ссылка на C++ практически (кроме разговорного использования этого термина), то проверьте определение его значения в выражении:
§5.5
Если выражение изначально имеет тип "ссылка на
T
"(8.3.2, 8.5.3), тип корректируется наT
до дальнейшего анализа. Выражение обозначает объект или функцию, обозначенную ссылкой, и выражение является lvalue или xvalue, в зависимости от выражения
Фактически это означает, что ссылка действует как псевдоним.
Вы можете рассматривать ссылку как автоматически разыменованную const
указатель, который объясняет большую часть поведения, за исключением того, что ссылка не обязательно занимает память (компилятор может полностью ее оптимизировать).
По мнению некоторых экспертов, ссылочные типы не являются ссылками на C++ как таковые, а в отличие от типов-значений. Я представляю два немного разных определения - типов значений и ссылочных типов.
https://abseil.io/blog/20180531-regular-types
Первый - это сообщение в блоге Титуса Винтерса, председателя подкомитета C++, ответственного за библиотеку стандартов C++.
По словам Титуса Винтерса, разница между типом значения и ссылочным типом заключается в поведении копирования. Когда вы копируете тип значения, вы получаете два независимых объекта, которые сначала равны, но могут отличаться после модификации одного из них. Когда вы копируете ссылочный тип, вы получаете два объекта, которые ссылаются на одни и те же данные.
Ссылочные типы не владеют своими данными. Некоторые ссылочные типы позволяют изменять упомянутые данные (например, диапазон), некоторые - нет (например, string_view). Оба приведенных примера весьма полезны для передачи параметров функции. Вызывающий функцию гарантирует, что базовые данные ссылочных типов не разрушаются во время вызова функции (как в случае с простыми ссылками C++).
https://docs.microsoft.com/en-us/cpp/cpp/value-types-modern-cpp?view=vs-2019
В документации Microsoft ссылочные типы рассматриваются как синонимы полиморфных типов (типы с хотя бы одной виртуальной функцией или переменной-членом), а типы значений - как неполиморфные. (Бьярне Страуструп назвал неполиморфные типы конкретными типами.)
Типы значений касаются управления памятью и макетом, ссылочные типы - идентичностью.
Типы значений позволяют компилятору прямой доступ к членам, ссылочные типы нуждаются в косвенном обращении из-за полиморфизма времени выполнения.
Справочные типы согласно Microsoft не подлежат копированию (для предотвращения нарезки).
Таким образом, семантика различается, поскольку Титус Винтерс определяет ссылочные типы по их фактическому поведению при копировании.
Основное различие между C и C++ (кроме Objects и Classes!) Заключается в ссылках. Ссылка похожа на константный указатель на переменную. Присвоение ссылки немного похоже на использование указателя, но с & not *, и вам не нужна разница. Разница в том, что вы назначаете адрес указателю, а переменную - ссылочной переменной. Строка ниже предполагает, что значение a копируется в aref. Но это не так, вместо этого aref является ссылкой на переменную a. После присвоения aref совпадает с. Любые изменения в aref являются изменениями, как показано в примере ниже.
int & aref = a;
#include <stdio.h>
#include "stdafx.h"
int main()
{
int a=9;
int & aref = a;
a++;
cout << "The value of a is %i\n" << aref;
return 0;
}
Также помните, что
Ссылка всегда должна ссылаться на что-то. Нулевые недопустимы.
Ссылка должна быть инициализирована при ее создании. Неназначенная ссылка не может существовать.
После инициализации его нельзя изменить на другую переменную.
Если это поможет вам, пожалуйста, сообщите мне, спасибо