Я изучаю ссылки в С++. В частности, я узнал, что ссылки не являются реальными объектами. Вместо этого они относятся к какому-то другому объекту. То есть ссылка — это просто псевдоним для других объектов.
Затем я наткнулся на это, в котором говорится:
Important note: Even though a reference is often implemented using an address in the underlying assembly language, please do not think of a reference as a funny looking pointer to an object. A reference is the object, just with another name. It is neither a pointer to the object, nor a copy of the object. It is the object. There is no C++ syntax that lets you operate on the reference itself separate from the object to which it refers.
Я понимаю, что приведенная выше цитата означает, что мы не можем работать с самой ссылкой отдельно от объекта, на который она ссылается, но все же кажется, подразумевает, что «ссылка является объектом».
Кроме того, я наткнулся на предложение, приведенное ниже:
In ISO C++, a reference is not an object. As such, it needs not have any memory representation.
У меня нет ссылки на эту вторую цитату, но я где-то прочитал ее в одном из постов SO.
Мой вопрос заключается в том, что если предположить, что вторая цитата также взята из стандарта (что может быть не так), разве эти два цитируемых утверждения не противоречат друг другу. Или, по крайней мере, первая цитата вводит в заблуждение. Который правильный.
Мое текущее понимание (путем чтения таких книг, как C++ Primer 5th edition) заключается в том, что ссылки являются псевдонимом для объектов. Это наводит меня на мысль, что они не должны занимать место в памяти.
Поправьте меня, если я ошибаюсь, но ссылки могут занимать место в памяти, а могут и не занимать. Он основан на компиляторе. Ссылка: stackoverflow.com/questions/39481687/…
Стандартная цитата — это примечание. Примечания носят неформальный характер и иногда противоречат правилам при слишком строгом толковании. В таком случае правила верны, а примечание — нет. Если вам нужна менее противоречивая формулировка, прочитайте ее как «ссылка называет объект».
В абстрактной концепции виртуальной машины C++ ссылка — это просто псевдоним объекта, на который она ссылается. Он вообще не должен существовать, как и using int_vec = std::vector<int>; создает псевдоним, он не создает новый тип. В техническом смысле может потребоваться указатель, чтобы компилятор мог передать дескриптор объекта, на который ссылается ссылка, но это всего лишь деталь реализации.
Чем «является» референция — это чисто философский вопрос; это абстрактное понятие, о котором люди могут думать по-разному. Но я не уверен в практической значимости. Есть ли конкретный фрагмент кода, чье наблюдаемое поведение, по вашему мнению, будет зависеть от этого?
Этот отрывок пытается сказать, что ссылка является псевдонимом — другим именем — для объекта, на который она ссылается. Объект ведет себя точно так же, независимо от того, какое имя вы используете для доступа к нему или управления им, будь то имя переменной в исходном определении или ссылка, привязанная к объекту позже. Как только ссылка объявлена и привязана к объекту, все, что вы делаете с этой ссылкой, фактически является операцией над объектом, на который делается ссылка.
Я думаю, что само имя тоже не занимает места, это объект, на который делается ссылка (или хранилище, когда нет активного объекта), который занимает место. (и безымянные временные тоже занимают место) (не язык-адвокат)
@NateEldredge Я думал подтвердить, что ссылки занимают место или нет, и знал, что компиляторы реализуют это с помощью указателей. Затем я подумал, что, поскольку указатели занимают место, ссылка также должна занимать место. Что противоречило моему нынешнему мнению, что ссылка - это просто псевдоним и не должна занимать место. Итак, я начал искать в Интернете ссылку и наткнулся на первую цитату, упомянутую в моем вопросе.
Независимо от того, «занимает ли что-либо место» — это деталь реализации, которая выходит за рамки стандарта. Однако с одной стороны вы не можете брать адрес ссылки; вы просто возвращаете адрес указанного объекта. Таким образом, реализация не является обязательный для выделения определенного фрагмента памяти для ссылки и не действует так, как если бы она это делала.
@SolvedGames Переменная всегда является объектом, все, что имеет имя, является объектом. Но вы также можете вернуть ссылку из функции, и возвращаемое значение будет не объектом, а rvalue. Вы должны присвоить его некоторой переменной, чтобы он стал объектом. Но иногда такие rvalue могут неявно становиться объектами, например. когда они преобразуются в другой тип при вызове функции: foo(bar()) где foo принимает ссылку, а bar возвращает ссылку другого типа, которая неявно преобразуется. Посмотреть это выступление youtube.com/watch?v=XS2JddPq7GQ
@GoswinvonBrederlow О, я буду иметь это в виду. Спасибо, что сообщили мне об этом.





Первая цитата на самом деле говорит, что ссылка не является отделимый от объектом.
... still seems to imply that "a reference is an object".
Это действительно подразумевает, что ссылка является неотделимым, непервоклассным псевдонимом для объекта, точно так, как вы сначала сказали.
Трудность этих дискуссий заключается в том, что стандартное значение слова «объект» уже отличается от значения, используемого в большинстве менее формальных контекстов.
Начнем с простого:
int a;
Часто это описывается как объявление целочисленного объекта a, верно? Это на самом деле
a к этому объекту в соответствующей областиТеперь, если мы напишем
int &b = a;
мы могли бы сказать, что bявляется объект, точно так же, как мы могли бы сказать, что a является объектом. На самом деле ни то, ни другое неверно, но, учитывая, что в неформальном тексте уже используется последнее, это не хуже.
Вместо этого мы должны сказать, что имя b относится к тому же объекту, что и имя a. Это точно согласуется с тем, чтобы называть его псевдонимом, но неформальные или вводные тексты кажутся довольно громоздкими, если они везде пишут «... целочисленный объект, на который ссылается имя a ...", а не просто «целое число a».
Насчет занимаемого места в памяти... бывает по разному. Если я введу 100 псевдонимов для одного объекта внутри одной функции, я был бы очень удивлен, если бы компилятор просто не свернул их (хотя, конечно, они все еще могут отображаться в символах отладки). Никакая информация не будет потеряна из-за исключения избыточных имен.
Если я передаю аргумент по ссылке на невстроенную функцию, передается фактическая информация некоторый, и эта информация должна где-то храниться.
Ваш первый пример имеет смысл. В частности, мне нравится второй пункт/деталь, где вы написали: «привязывает имя a к этому объекту в соответствующей области». Только один вопрос: это (второй пункт) то, что должно происходить в соответствии со стандартом C++ или другой деталью реализации?
Ссылки не обязаны занимать место, за исключением случаев, когда они не могут правильно функционировать без места: вот почему я упомянул передачу параметра функции по ссылке. Стандарт по-прежнему не требует места для хранения, но реализация соглашения о вызовах, вероятно, требует.
a к этому объекту в соответствующей области Вы имеете в виду «переменная» вместо «объект»?
Нет. Объявление делает вводит переменную, потому что это ссылка на объект, но я обсуждаю различие между самим объектом и ссылкой. Это категории (неправильно) используемые в исходных цитатах, и я не думаю, что добавление 3-й перекрывающейся категории что-то прояснит.
Я просто не думаю, что мы говорим «привязать имя к объекту», а скорее «к переменной».
@LanguageLawyer Объект и переменная одинаковы в этом контексте (или в любом контексте?), верно? Так что это не должно иметь значения. Я могу ошибаться. Пожалуйста, поправьте меня, указав на статью/источник, объясняющую разницу.
@Аня Объект и переменная одинаковы в этом контексте (или в любом контексте?), верно? Нет.
Я второй @LanguageLawyer здесь.
@LanguageLawyer Я задал отдельный вопрос здесь по этому поводу. cppref говорит: «Переменная — это объект или ссылка, которая не является нестатическим элементом данных и вводится объявлением».. Таким образом, переменная и объект кажутся одинаковыми (за исключением, конечно, нестатического члена данных).
@Anya Я задал отдельный вопрос... переменная и объект вроде одно и то же AFAIR об этом уже спрашивали пару раз
Important note: Even though a reference is often implemented using an address in the underlying assembly language, please do not think of a reference as a funny looking pointer to an object. A reference is the object, just with another name. ...
Примечания носят неформальный характер и обычно не должны интерпретироваться как строгие правила. Если интерпретация противоречит стандартным правилам, то эта интерпретация неверна.
Ссылки и объекты — это разные виды сущностей. Ссылка не является объектом, отличным от того, который она называет. Невозможно сформировать указатель на ссылку. «Указатель на ссылку» даже не является допустимой категорией типа.
В примечании делается попытка сказать, что ссылка «является» объектом, который она называет, в том смысле, что использование ссылки означает использование объекта, на который делается ссылка.
I was thinking of confirming that whether or not references take any space
Ссылки занимают место или не занимают места. Реализация языка должна выяснить, нужно ли ей место в каждом случае.
Стандартная цитата:
[dcl.ref] It is unspecified whether or not a reference requires storage
Вне стандартных спецификаций, если вам нужен пример ссылки с использованием пробела, попробуйте добавить элемент ссылки в класс, и вы, скорее всего, заметите, что размер класса увеличивается.
since pointers take space then reference should also take space. ...
Указатели занимают место в абстрактной машине, указанной в стандарте. Но если вы никогда не наблюдаете хранилище, то вполне возможно, что хранилище никогда не существует на практике. Существенная разница между ссылками и указателями заключается в том, что вы не можете напрямую наблюдать за хранением ссылки.
Философ: «Если дерево падает в абстрактная машина, и никто не видит его, значит, это иметь эффект?»
Оптимизатор: «Нет, если я могу помочь».
Итак, правильно ли говорить, что в соответствии со стандартом ссылка является псевдонимом для другого объекта. Но стандарт не требует, чтобы ссылки не занимали места. Реализации могут свободно реализовывать ссылку по своему усмотрению, если она соответствует поведению ссылки, как описано в стандарте?
@Аня Да, именно так.
Да. Рассмотрим в качестве контраста реальные первоклассные объекты, которые имеют указанные минимальные размеры и должны быть адресуемыми.
То, чем на самом деле является ссылка, не имеет особого смысла: вы можете сказать, что это объект, на который делается ссылка, или что это его псевдоним, и оба эти утверждения в некотором смысле верны.
int main()
{
int a(0);
int& ref(a);
ref = 1; // Will actually affect the value of a
return 0;
}
Давайте пройдемся по этой программе построчно.
int a(0); выделяет часть памяти (обычно 4 байта) в стеке для хранения целого числа.int& ref(a);не обязательно выделяет память, и будет ли это на самом деле, зависит от компилятора. В этом смысле ref сам по себе не является объектом: это просто псевдоним, другое имя для a. Это то, что вторая цитата означает «ссылка не является объектом». (Обратите внимание, что иногда, когда объект, на который ссылаются, не может быть известен, например, во время компиляции, ссылка должна резервировать дополнительное пространство для адреса объекта. В этих случаях ссылки — это просто синтаксический сахар для указателей.)ref = 1; устанавливает значение a равным единице. В этом смысле вы можете думать о ref как о том же объекте, что и a. Любая операция «над» ссылкой будет фактически выполняться над объектом, на который делается ссылка. Это то, что первая цитата означает "Это объект".Поскольку это вопрос типа языкового юриста, сохраняющий аннотацию, вам следует заменить использование разговорного термина «стек» на «автоматическое хранение», чтобы сохранить правильность. Точно так же В этих случаях ссылки — это просто синтаксический сахар для указателей. было бы лучше сформулировать как В этих случаях ссылки часто являются просто синтаксическим сахаром для указателей. или В этих случаях ссылки обычно реализуются с помощью указателей., потому что, насколько это касается Стандарта, реализация может использовать магию Эльдар или квантовую запутанность для выполнения работы.
Ссылка обеспечивает еще один способ обращения к объекту. Это особенно полезно при передаче параметров по ссылке функциям. Более формально ссылка — это псевдоним, которая связывается с переменная, включая, в данном случае, анонимный временный.
К счастью, нам не нужно заботиться о том, как они реализуются. Это работа компилятора, и методы различаются. Стандарт C++ не требует, чтобы они занимали какую-либо память.
Между прочим, есть является способ различать ссылочные типы. Неотделимость на самом деле больше связана с невозможностью привязать ссылку к какой-либо другой переменной. Видеть
#include <iostream>
#include <type_traits>
int main() {
int a = 0;
int& ref = a;
std::cout << (
std::is_reference<decltype(ref)>::value ? "pay me a bonus\n" : "reformat my hard disk\n"
);
std::cout << (
std::is_reference<decltype(a)>::value ? "pay me a bonus\n" : "reformat my hard disk\n"
);
}
Наконец, обратите внимание, что &a и &ref всегда должны быть одинаковыми.
Когда первая цитата говорит Это объект, это говорит не о том, что ссылка является объектом, а о том, что ссылка является упомянутый объект.