Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: L-величина и R-величина  (Прочитано 42726 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Olegator
Команда клуба

ru
Offline Offline
Пол: Мужской

« : 30-12-2005 23:41 » 

Цитата из учебника "Как программировать на С++" Дейтел Х., Дейтел П.
Цитата
Ссылочные переменные должны получать начальные условия в их объявлениях (смотри рис. 3.21 и рис. 3.22) и не могут переприсваиваться как псевдонимы другим переменным. Как только ссылка объявляется как псевдоним другой перемен¬ной, все операции, выполняемые с псевдонимом (т.е. ссылкой), на самом деле будут выполняться с самой истинной переменной. Псевдоним — лишь другое имя для истинной переменной, для него не резервируется никакого места в памяти. Определение адреса ссылки и сравнение ссылок не вызывают синтаксических ошибок; на самом деле каждая операция выполняется над переменной, для которой ссылка является псевдонимом. Аргумент-ссылка должен быть L-величиной, не константой и не выражением, которое возвращает R-величину.
Что означает L-величина и R-величина?
Может L-величина есть положительное целое число?
« Последнее редактирование: 30-12-2005 23:48 от Olegator » Записан
Finch
Спокойный
Администратор

il
Offline 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
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 31-12-2005 08:15 » 

В книжке ссылочная переменная объявляется не так, как у тебя.
Код:
int x = 1;
int  &y = x; // создание y, как псевдонима для x.
Значит можно и так и так?
Кроме того написано, что ссылочные переменные должны получать начальные условия в их объявлениях.
« Последнее редактирование: 31-12-2005 08:17 от Olegator » Записан
LP
Помогающий

ru
Offline 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' и т.д.) и временные объекты.
например,
Код:
std::string(); // rvalue
это временный объект типа 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
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #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
Помогающий

ru
Offline 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
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 11-01-2006 10:44 » 

Понять это невозможно, это надо запомнить Улыбаюсь  Что является Lvalue, а что Rvalue.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #7 : 11-01-2006 11:13 » 

Понять это невозможно, это надо запомнить Улыбаюсь  Что является Lvalue, а что Rvalue.


а я даже никогда и не задумывался об этом Улыбаюсь - в смысле , что есть L , а что R
Записан

npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 11-01-2006 11:52 » 

По большому счёту это редко требуется.  Только в разных выморочных случаях, таких как
почему (++i)++ компилируется, а ++(i++) нет.  Или почему
int & x = i++ не компилируется, а
int & x = ++i компилируется
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Hooter
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #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
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 11-01-2006 12:47 » 

Да?

Тогда почему int& operator++() нельзя применять к результату оператора int operator++(int) ?
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Hooter
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 11-01-2006 12:54 » 

Тогда почему int& operator++() нельзя применять к результату оператора int operator++(int) ?
Насколько я вижу, результатом оператора int operator++(int) является int (то есть число). Возвращаемый результат нельзя изменить. Поэтому ++(i++) - не откомпилируется.
А результатом оператора int& operator++() - является ссылка на тип int. Поэтому (++i)++ - работает.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #12 : 11-01-2006 13:08 » 

npak ,Hooter

всё гораздо проще Улыбаюсь Просто не надо такие фокусы писать.
     можно просто и по человечьи:
   i++;
   ++i;

   Улыбаюсь
Записан

Hooter
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #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 рулит!! Улыбаюсь
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #16 : 11-01-2006 13:25 » 

не,

++i = i++;
и
i++ = ++i;
- это всё же извращение Улыбаюсь
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #17 : 11-01-2006 13:26 » 

это больше проверка компилятора (или программиста?) на вшивость Отлично
Записан

PooH
Глобальный модератор

ru
Offline Offline
Пол: Мужской
... и можно без хлеба!


« Ответ #18 : 11-01-2006 13:29 » 

так

--I=I--

красивше! Улыбаюсь))

или так

I-=I

--O=O-- (очки)
« Последнее редактирование: 11-01-2006 13:32 от PooH » Записан

Удачного всем кодинга! -=x[PooH]x=-
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #19 : 11-01-2006 13:32 » 

не откомпилиться ни то, ни то Улыбаюсь)))    семиколон нету! Улыбаюсь)

;--I=I-- ;

;I-=I;

(это турбулентные завихрения Улыбаюсь )
Записан

REM
Гость
« Ответ #20 : 11-01-2006 13:35 » 

не,

++i = i++;
и
i++ = ++i;
- это всё же извращение Улыбаюсь

Конечно, извращение. Но ведь здорово, правда?  Отлично
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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) ++;
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #23 : 11-01-2006 14:00 » 

мыного! Улыбаюсь)
Записан

Anestezia
Новенький

ua
Offline Offline

« Ответ #24 : 13-09-2012 08:00 » 

Почитайте эту заметку: http://hashcode.ru/questions/53113
Очень доходчиво написано, в чем разница между  value и  rvalue
« Последнее редактирование: 13-09-2012 08:40 от RXL » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #25 : 13-09-2012 08:07 » 

Anestezia, не забываем обращать внимание на дату сообщения Улыбаюсь
Записан

ezus
Опытный

il
Offline Offline

« Ответ #26 : 03-12-2012 14:39 » 

Алексей++, на дату я вимание обратил.
Просто не совсем корректное дополнение на будующее.

Мне в свое время разницу между L-value и R-value объяснили просто:
L-value - это то, что может стоять слева от '=', т.е. это адрес,
а R-value - только справа, т.е. это значение.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #27 : 05-12-2012 03:37 » 

ezus, L - необязательно адрес. Это любая изменяемая переменная. R - может быть как L, так и константа
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #28 : 05-12-2012 05:55 » 

Леш, это именно адрес, ссылка на значение — не значение. По адресу можно как прочитать, так и записать. Значение read only по своей сути. И не важно, переменная это или еще как-то называется. При этом в каждом языке могут быть свои заморочки, касающиеся правил управления памятью.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #29 : 05-12-2012 08:54 » new

Надо заметить, что понятия применимы не только к оператору присваивания, но и к параметрам процедур и функций. Вернее даже так: для общности самый оператор присваивания - одна из функций, имеющая особую синтаксическую запись (что в C++ совершенно так). Так что уместнее говорить не о левой и правой части относительно оператора, а о разнице между формальными и фактическими параметрами функции. Возможно, в такой интерпретации путаницы будет меньше.

Всегда ищите женщину функцию. Улыбаюсь
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines