Olegator
|
|
« : 30-12-2005 23:41 » |
|
Цитата из учебника "Как программировать на С++" Дейтел Х., Дейтел П. Ссылочные переменные должны получать начальные условия в их объявлениях (смотри рис. 3.21 и рис. 3.22) и не могут переприсваиваться как псевдонимы другим переменным. Как только ссылка объявляется как псевдоним другой перемен¬ной, все операции, выполняемые с псевдонимом (т.е. ссылкой), на самом деле будут выполняться с самой истинной переменной. Псевдоним — лишь другое имя для истинной переменной, для него не резервируется никакого места в памяти. Определение адреса ссылки и сравнение ссылок не вызывают синтаксических ошибок; на самом деле каждая операция выполняется над переменной, для которой ссылка является псевдонимом. Аргумент-ссылка должен быть L-величиной, не константой и не выражением, которое возвращает R-величину. Что означает L-величина и R-величина? Может L-величина есть положительное целое число?
|
|
« Последнее редактирование: 30-12-2005 23:48 от Olegator »
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #1 : 31-12-2005 07:10 » |
|
L-величина это адрес. Ссылочная переменная занимает в памяти для 32 разрядных систем 4 байта. Если ты определил const int c=5; int a; int *b;
Если ты делаеш b=a; То компилятор должен дать ошибку компиляции. Так как ты нарушаеш L-порядок. Пытаешся ссылочной переменной присвоить значение a. У меня компилятор выдал такую ошибку "error C2440: '=' : cannot convert from 'int' to 'int *'" Если ты делаеш b=&a;. Получаеш псевдоним переменной а. Любое изменение переменной по ссылке b будет приводить изменению a. Насчет констант: такую строчку у меня компилятор пропустил b=(int *)&c; Но если я попытаюсь изменить значение по ссылке b, будет выдана ошибка исполнения. Так как программа будет пытаться залезть в зашишенную область памяти. Константы VC размешает в памяти в зашишенной области. Хотя я слышал о библиотеки, которая позволяет также менять и константы. Помоему называется RTII.
|
|
« Последнее редактирование: 20-12-2007 18:00 от Алексей1153++ »
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
Olegator
|
|
« Ответ #2 : 31-12-2005 08:15 » |
|
В книжке ссылочная переменная объявляется не так, как у тебя. int x = 1; int &y = x; // создание y, как псевдонима для x.
Значит можно и так и так? Кроме того написано, что ссылочные переменные должны получать начальные условия в их объявлениях.
|
|
« Последнее редактирование: 31-12-2005 08:17 от Olegator »
|
Записан
|
|
|
|
LP
Помогающий
Offline
|
|
« Ответ #3 : 31-12-2005 08:29 » |
|
Аргумент-ссылка должен быть L-величиной, не константой и не выражением, которое возвращает R-величину.
Lvalue и rvalue это несколько запутанные термины... Lvalue-объект хранится где-то в памяти и имеет некоторый адрес. Например: int i = 7;// i это lvalue
А константа "7" это rvalue. Rvalue, с точки зрения компилятора, не имеет адреса в памяти. Rvalue являются литералы (7, 0.0, 'A' и т.д.) и временные объекты. например, это временный объект типа string, который уничтожается в конце полного выражения, в данном случае после точки с запятой ;. Т.е. авторы хотели, видимо, сказать вот что: int i = 4; int& ref = i; //инициализация допустима, т.к. i это lvalue ... int& ref2 = 5;// ошибка, так как "5" это rvalue. ... int f1() {return 1;} int& f2() {static int s = 1; return s;} int& ref3 = f1(); // ошибка, функция f1 возвращает временное значение - rvalue int& ref4 = f2(); // правильно, функция возвращает ссылку ... int i = 5; int& ref5 = (int)i; // ошибка, так как по стандарту, результат преобразования в нессылочный тип яв-ся rvalue
По словам Страуструпа запрет на инициализацию ссылки rvalue был наложен, так как это вызывало труднонаходимые ошибки. Не понятно, что должен ожидать программист модифицируя rvalue через ссылку. Однако, ссылки на константу можно инициализировать rvalue. const int& cref = 4; //ok
P.S. Некоторые распространенные компиляторы, нарушают некоторые из этих правил стандарта. Вот здесь еще есть статья. http://rsdn.ru/article/cpp/lvalue.xml
|
|
« Последнее редактирование: 20-12-2007 18:02 от Алексей1153++ »
|
Записан
|
Если эта надпись уменьшается, значит ваш монитор уносят
|
|
|
Olegator
|
|
« Ответ #4 : 31-12-2005 11:26 » |
|
Т.е. L- и R-величины это обозначение двух понятий, которые совместимы только одноимённо кроме ссылки на константу. (L-L) и (R-R) и ((const L)-R) и not(R-L) и not(L-R). Для простоты общения. "обозначай и властвуй". Т.е. можно теперь делать так. Если возникла ошибка, можно говорить что вот здесь L, а здесь R. А потом показываешь на таблицу, что к чему относится. Т.е. проще абстрогироваться от железа. Если конечно точно знать критерии что есть L и R. Или нет. Просто так удобнее.
|
|
« Последнее редактирование: 31-12-2005 11:43 от Olegator »
|
Записан
|
|
|
|
LP
Помогающий
Offline
|
|
« Ответ #5 : 31-12-2005 12:22 » |
|
Я немного не понял таблицу... Смысл, ИМХО, таков. Литералы и временные объекты (т.е. R-значения) запрещено модифицировать, 6 = 1;// нельзя ... int f() { int i = 4; return i; }
++f();//нельзя, возвращаемое значение функций является r-значением
так как это не интуитивно или чревато ошибками (по крайней мере, по мнению разработчиков С++). Если бы было разрешено инициализировать ссылку R-значением, то этот запрет можно было бы обойти и мы получили бы возможность изменить r-значение посредством ссылки. Инициализировать ссылку на константу, R-значением можно, т.к. модифицировать объект с помощью ссылки на константу мы не можем в любом случае. const int& cr = 1;//ссылка на константу инициализируется r-значением //Ошибки нет, т.к. модифицировать объект посредством такой ссылки нельзя
|
|
« Последнее редактирование: 31-12-2005 12:29 от LP »
|
Записан
|
Если эта надпись уменьшается, значит ваш монитор уносят
|
|
|
npak
|
|
« Ответ #6 : 11-01-2006 10:44 » |
|
Понять это невозможно, это надо запомнить Что является Lvalue, а что Rvalue.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #7 : 11-01-2006 11:13 » |
|
Понять это невозможно, это надо запомнить Что является Lvalue, а что Rvalue. а я даже никогда и не задумывался об этом - в смысле , что есть L , а что R
|
|
|
Записан
|
|
|
|
npak
|
|
« Ответ #8 : 11-01-2006 11:52 » |
|
По большому счёту это редко требуется. Только в разных выморочных случаях, таких как почему (++i)++ компилируется, а ++(i++) нет. Или почему int & x = i++ не компилируется, а int & x = ++i компилируется
|
|
|
Записан
|
|
|
|
Hooter
|
|
« Ответ #9 : 11-01-2006 12:33 » |
|
По большому счёту это редко требуется. Только в разных выморочных случаях, таких как почему (++i)++ компилируется, а ++(i++) нет. Или почему int & x = i++ не компилируется, а int & x = ++i компилируется
А разве не поэтому? int& operator++(); // для ++i int operator++(int); // для i++
В приведенных случаях даже запоминать не надо. Можно посмотреть как объявлены операторы.
|
|
« Последнее редактирование: 11-01-2006 12:35 от Hooter »
|
Записан
|
|
|
|
npak
|
|
« Ответ #10 : 11-01-2006 12:47 » |
|
Да?
Тогда почему int& operator++() нельзя применять к результату оператора int operator++(int) ?
|
|
|
Записан
|
|
|
|
Hooter
|
|
« Ответ #11 : 11-01-2006 12:54 » |
|
Тогда почему int& operator++() нельзя применять к результату оператора int operator++(int) ?
Насколько я вижу, результатом оператора int operator++(int) является int (то есть число). Возвращаемый результат нельзя изменить. Поэтому ++(i++) - не откомпилируется. А результатом оператора int& operator++() - является ссылка на тип int. Поэтому (++i)++ - работает.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #12 : 11-01-2006 13:08 » |
|
npak ,Hooter всё гораздо проще Просто не надо такие фокусы писать. можно просто и по человечьи: i++; ++i;
|
|
|
Записан
|
|
|
|
Hooter
|
|
« Ответ #13 : 11-01-2006 13:09 » |
|
а можно так: i += 2;
|
|
|
Записан
|
|
|
|
REM
Гость
|
|
« Ответ #14 : 11-01-2006 13:12 » |
|
А можно и так i = 0; ++i = i++;
|
|
|
Записан
|
|
|
|
REM
Гость
|
|
« Ответ #15 : 11-01-2006 13:14 » |
|
А так, соответственно нельзя: i++ = ++i; ++C рулит!!
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #16 : 11-01-2006 13:25 » |
|
не, ++i = i++; и i++ = ++i; - это всё же извращение
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #17 : 11-01-2006 13:26 » |
|
это больше проверка компилятора (или программиста?) на вшивость
|
|
|
Записан
|
|
|
|
PooH
Глобальный модератор
Offline
Пол:
... и можно без хлеба!
|
|
« Ответ #18 : 11-01-2006 13:29 » |
|
так --I=I-- красивше! )) или так I-=I --O=O-- (очки)
|
|
« Последнее редактирование: 11-01-2006 13:32 от PooH »
|
Записан
|
Удачного всем кодинга! -=x[PooH]x=-
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #19 : 11-01-2006 13:32 » |
|
не откомпилиться ни то, ни то ))) семиколон нету! ) ;--I=I-- ; ;I-=I; (это турбулентные завихрения )
|
|
|
Записан
|
|
|
|
REM
Гость
|
|
« Ответ #20 : 11-01-2006 13:35 » |
|
не, ++i = i++; и i++ = ++i; - это всё же извращение Конечно, извращение. Но ведь здорово, правда?
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #21 : 11-01-2006 13:43 » |
|
нет, не здорОво
|
|
|
Записан
|
|
|
|
REM
Гость
|
|
« Ответ #22 : 11-01-2006 13:54 » |
|
Ну-ка, чему равен i, а чему j? int i = 0, j = 0; j= ++i = (++i)++ + + + + ( + i) ++;
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #23 : 11-01-2006 14:00 » |
|
мыного! )
|
|
|
Записан
|
|
|
|
Anestezia
Новенький
Offline
|
|
« Ответ #24 : 13-09-2012 08:00 » |
|
Почитайте эту заметку: http://hashcode.ru/questions/53113 Очень доходчиво написано, в чем разница между value и rvalue
|
|
« Последнее редактирование: 13-09-2012 08:40 от RXL »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #25 : 13-09-2012 08:07 » |
|
Anestezia, не забываем обращать внимание на дату сообщения
|
|
|
Записан
|
|
|
|
ezus
Опытный
Offline
|
|
« Ответ #26 : 03-12-2012 14:39 » |
|
Алексей++, на дату я вимание обратил. Просто не совсем корректное дополнение на будующее.
Мне в свое время разницу между L-value и R-value объяснили просто: L-value - это то, что может стоять слева от '=', т.е. это адрес, а R-value - только справа, т.е. это значение.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #27 : 05-12-2012 03:37 » |
|
ezus, L - необязательно адрес. Это любая изменяемая переменная. R - может быть как L, так и константа
|
|
|
Записан
|
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #28 : 05-12-2012 05:55 » |
|
Леш, это именно адрес, ссылка на значение — не значение. По адресу можно как прочитать, так и записать. Значение read only по своей сути. И не важно, переменная это или еще как-то называется. При этом в каждом языке могут быть свои заморочки, касающиеся правил управления памятью.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #29 : 05-12-2012 08:54 » |
|
Надо заметить, что понятия применимы не только к оператору присваивания, но и к параметрам процедур и функций. Вернее даже так: для общности самый оператор присваивания - одна из функций, имеющая особую синтаксическую запись (что в C++ совершенно так). Так что уместнее говорить не о левой и правой части относительно оператора, а о разнице между формальными и фактическими параметрами функции. Возможно, в такой интерпретации путаницы будет меньше. Всегда ищите женщину функцию.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
|