Доброго времени суток всем. Почитал диалоги на форуме, да впринципе почти все уже сказали и
выяснили, что есть ссылка что есть указатель, остается только просуммировать и подытожить.
Тем не менее были и грубые ошибки типа:
class TC
{
public:
//ссылка x будет занимать место в стековой памяти
// ... если компилятор не встроит конструктор в точку вызова (я про inline)
TC(int& x):m_rx(x){;}
private:
int& m_rx;//вот тут память под ссылку тоже однозначно будет выделена
};//class TC
Этот пример даже не скомпилируется, потому что ссылка инициализируется сразу.
Но это не суть важно

важно то что в споре рождается истина а истина — новое
знание, другое дело имеет это знание практическое применение.
Это тоже не откомпилируется:
struct STR{
int a;
float b;
int& la=a;
float& lb=b;
}
ссылки как оказывается имеют ограниченную область применения. Об этом позже.
Вопрос был такой:
"Недавно один товарищ на мой вопрос по языку С++ заметил «У… батенька мы даже не знаем разницы между
ссылкой и указателем! Темнота!..» Для меня, честно говоря, это оказалось откровением. В литературе я
не встречал чёткого разграничения этих понятий и воспринимал их как синонимы. Поиски ничего не дали.
Так в чём же разница?"
Здесь можно подойти к ответу с двух основных точек зрения:
— как, зачем и когда использовать указатели и ссылки в программе, каковы их сходства и отличия;
— как компилятор оптимизирует представление этих объектов в машинном коде (напр исп памяти);
Рассмотрим по порядку.
Указатели были введены в язык С для реализации возможностей работы с памятью в частности с кучей,
для передачи параметров из функций, для поддержки механизма обратного вызова (указатель на функцию).
Кроме того указатели это встроенный тип данных с которым можно производить некоторые арифметические
операции, присваивание, разыменование, приведение.
Ссылки же были введены в язык С++ как средство частичной замены функции указателей при передаче параметров
из функций. Ссылка это псевдоним имени переменной не более того. И ссылка это не встроенный тип данных в
том смысле, что ее можно использовать как все другие типы.
Главный идеолог языка С++ Бьерн Страуструп в своей общеизвестной книге "Язык программирования С++"
отмечает следующее (цитирую):
1) Ни один оператор не выполняет действий над ссылкой;
2) Инициализация ссылки отличается от присваивания ей значения;
3) Реализована ссылка как константный указатель при каждом использовании которого происходит разыменование;
4) В некоторых случаях компилятор может оптимизировать ссылку таким образом, что во время выполнения вообще не
будет существовать объекта представляющего ссылку;
Вот мы и подошли ко второй точке зрения на обсуждаемые объекты. Это во многом интересный вопрос и в тоже
время бесполезный. Ну что толку с того что под ссылки компилятор не резервирует памяти, или ничего не
заталкивает в стек? А если выделяет, то много ли памяти занимают эти объекты. Нужно понимать что цель ссылок
не в том чтобы экономить память (или что-то другое) путем новых изобретенных синтаксических конструкций языка.
Но все же интересно, как представляются в памяти ссылки если они вообще представляются. Бьерн говорит об
оптимизации компилятором кода, но не исключает возможности размещения ссылок в памяти.
Что ж лучший ответ на этот вопрос даст сам компилятор. Обратимся к нему. Ниже я привожу код на С++ который
мы проанализируем после дизасемблирования. Цель посмотреть что представляют собой ссылки при передаче
значений параметров из функций сравнить это же с указателями. Как ссылки определяются в программе и что этому
соответствует в машинном коде. Пример создавался и тестился в среде VS2005, (пример с классами и прочими
конструкциями только усложнит анализ) все ключи МАKE-раздела компиляции и сборки оставлены по умолчанию.
Каждый может проверить это собственноручно. Итак:
void link_use(int& l1, int& l2, float& l3)
{
l1 = 100;
l2 = 200;
l3 = 0.3;
}
void point_use(int* l1, int* l2, float* l3)
{
*l1 = 1000;
*l2 = 2000;
*l3 = 0.03;
}
void noret_use(int l1, int l2, float l3)
{
l1 = 100;
l2 = 200;
l3 = 0.3;
}
int _tmain(int argc, _TCHAR* argv[])
{
int i1=0,
i2=0;
float i3=0;
float& l3=i3;
const int& li2 = 10;
link_use(i1, i2, i3);
point_use(&i1, &i2, &i3);
noret_use(i1, i2, i3);
return 0;
}
Дизасемблируем (>Debug.Disassembly) и получаем:
--- c:\documents and settings\aan\my documents\visual studio 2005\projects\links\links\links.cpp
int _tmain(int argc, _TCHAR* argv[])
{
1 004135E0 push ebp
2 004135E1 mov ebp,esp
3 004135E3 sub esp,108h
4 004135E9 push ebx
5 004135EA push esi
6 004135EB push edi
7 004135EC lea edi,[ebp-108h]
8 004135F2 mov ecx,42h
9 004135F7 mov eax,0CCCCCCCCh
10 004135FC rep stos dword ptr es:[edi]
int i1=0,
11 004135FE mov dword ptr [i1],0
i2=0;
12 00413605 mov dword ptr [i2],0
float i3=0;
13 0041360C fldz
14 0041360E fstp dword ptr [i3]
float& l3=i3;
15 00413611 lea eax,[i3]
16 00413614 mov dword ptr [l3],eax
const int& li2 = 10;
17 00413617 mov dword ptr [ebp-44h],0Ah
18 0041361E lea eax,[ebp-44h]
19 00413621 mov dword ptr [li2],eax
link_use(i1, i2, i3);
20 00413624 lea eax,[i3]
21 00413627 push eax
22 00413628 lea ecx,[i2]
23 0041362B push ecx
24 0041362C lea edx,[i1]
25 0041362F push edx
26 00413630 call link_use (411118h)
27 00413635 add esp,0Ch
point_use(&i1, &i2, &i3);
28 00413638 lea eax,[i3]
29 0041363B push eax
30 0041363C lea ecx,[i2]
31 0041363F push ecx
32 00413640 lea edx,[i1]
33 00413643 push edx
34 00413644 call point_use (4111C7h)
35 00413649 add esp,0Ch
noret_use(i1, i2, i3);
36 0041364C push ecx
37 0041364D fld dword ptr [i3]
38 00413650 fstp dword ptr [esp]
39 00413653 mov eax,dword ptr [i2]
40 00413656 push eax
41 00413657 mov ecx,dword ptr [i1]
42 0041365A push ecx
43 00 41365B call noret_use (4111CCh)
44 00413660 add esp,0Ch
return 0;
45 00413663 xor eax,eax
}
Что же здесь мы видим? Для определения float& l3=i3;
в строках 15 и 16 ясно видно что никакого места
под ссылку не выделяется, (если конечно вспомним что делает команда lea)
А вот далее интереснее
Для конструкции const int& li2 = 10;
в строке 17 используется память для
хранения константы. А далее в строке 18 получаем смещение этой ячейки,
а встроке 19 (внимание) используется ячейка памяти для хранения ссылки
на константу. Причем рамер ее как видно 32 бита. Наталкивает на мысль
что это ни что иное как указатель, который нельзя поменять. Конечно
кто-то может поспорить что это некорректное определение константы, но это
работает и Бьерн приводит такой же пример задания ссылки.
Далее анализируя вызовы функций приходим к выводу что они абсолютно идентичны
для указателей и для ссылок. Для передачи параметров из функций используется стек.
Очевидно не так ли.
Что же мы имеем в итоге. Оказывается память под ссылку может как выделяться так и не
выделяться. Это зависит от написанного кода. В общем случае конечно.
Есть еще такое как оптимизация и около 200 различных С компиляторов. И каждый
может по своему это оптимизировать.
Но передачей параметров ясно, что стек используется.
Кроме оптимизации и определенно написанного исходника есть еще стандарт, но это
уже тема отдельного разговора. Отмечу только то что в компиляторах
реализованных по стандарту ISO/IEC 14882, ссылки задаются и работают корректно,
так что приведенные вначале примеры вообще не скомпилируются, а пример со структурой
в которой ссылки, компилятор VS2005 выведет вот что:
Error 1 error C2327: 'STR::a' : is not a type name, static, or enumerator
c:\documents and settings\aan\my documents\visual studio 2005\projects\links\links\links.cpp 10
Error 2 error C2065: 'a' : undeclared identifier
c:\documents and settings\aan\my documents\visual studio 2005\projects\links\links\links.cpp 10
Error 3 error C2864: 'STR::la' : only static const integral data members can be initialized within a class
С:\documents and settings\aan\my documents\visual studio 2005\projects\links\links\links.cpp 10
Error 4 error C2327: 'STR::b' : is not a type name, static, or enumerator
c:\documents and settings\aan\my documents\visual studio 2005\projects\links\links\links.cpp 11
Error 5 error C2065: 'b' : undeclared identifier
c:\documents and settings\aan\my documents\visual studio 2005\projects\links\links\links.cpp 11
Error 6 error C2864: 'STR::lb' : only static const integral data members can be initialized within a class
c:\documents and settings\aan\my documents\visual studio 2005\projects\links\links\links.cpp 11
Так что если у кого-то или где-то в каком-то компиляторе такое задание возможно, значит это несоответствие
стандартам или свой собственный стандарт (что вполне может быть).
В заключении отмечу, что ни один C++ компилятор на 100% не соответствует ни одному стандарту, более того
часто отступают от него, добавляют свои конструкции, и майкросовтовский тут не исключение.
Глюк случился..
Вместо моей мессаги отправилась какая-то левая.
Тем не менее, повторю вопрос.
Я долгое время работал только на бейсике, паскале, знал что такое переменная, константа и радовался жизни.
Теперь же, изучая C++, меня подвергли в шок такие понятия как ссылка, указатель. Я пытался понять что это такое, ища ответ в трех разных учебниках, но так и не понял (после паскаля, бейсика,мне сложно все это понять).
Поясните плиз или подскажите, где можно объяняются эти понятия человеческим, нормальным языком.