MyTetra Share
Делитесь знаниями!
Почему строковый литерал в C++ является lvalue?
Время создания: 31.05.2023 10:48
Автор: Xintrea
Текстовые метки: c++, язык, lvalue, rvalue, строка, литерал
Раздел: Компьютер - Программирование - Язык C++ (Си++)
Запись: xintrea/mytetra_syncro/master/base/16855192822gps4fj98y/text.html на raw.github.com

Имеется список типов, в котором перечисляется. что может являться lvalue, а что rvalue. В этом списке написано, что тип Строковый литерал является lvalue:



l-value:


  • Выражения, непосредственно обозначающие объект, non-modifiable в случае const-квалификации. Например, имя переменной, параметра функции и т.п.
  • Выражения ссылочных типов. non-modifiable в случае const-квалификации. В частности, результат вызова функций, возвращающих объекты по ссылке; выражения, состоящие из имен ссылочных переменных; операции преобразования к ссылочному типу и т.д.
  • Результат встроенной операции разыменования (*) — lvalue указуемого типа; non-modifiable в случае const-квалификации.
  • Результат встроенных префиксных операций ++, --.
  • Имя функции.
  • Имя массива.
  • Строковые литералы. - Вот это что за?



r-value:


  • Выражения, обозначающие временные объекты. В частности, результат вызова функций, возвращающих объекты не по ссылке; результат встроенных операций +, -. > *, / и т.п.; явное создание временной переменной int() или C(); преобразования не к ссылочным типам и т.д.
  • Результат встроенной операции взятия адреса (&) — rvalue типа указатель.
  • Результат встроенных постфиксных операций ++, --.
  • Литералы, за исключением строковых (например, числовые литералы).
  • Константы перечислений.



Возникает вопрос, а почему строковый литерал является l-value? Ведь нельзя написать так:



"This is str-literal" = "Any value";



А дело в том, что термины l-value и r-value по историческим причинам не отражают того, чем они на самом деле являются. l-value - это не просто "нечто, что стоит слева от знака присвоения". То же самое касается и r-value.



Более точным определением l-value будет такое: l-value - это некий объект в памяти, от которого можно взять адрес.



Обычно для того, чтобы произошло присвоение через память, надо знать, куда в памяти в конечном итоге будет положено присваимоемое значение. И именно поэтому, чтобы присвоение состоялось, присвоение должно происходить с такой сущностью, у которой адрес имеется.


С другой стороны, строка - это такая сущность, которая всегда размещена в памяти, и у нее есть адрес начала строки. А коль у нее есть адрес, значит таковой объект является l-value. В этом и состоит ответ на вопрос, заданный в заголовке.



Подытоживая, можно сказать: принадлежность к l-value совершенно не значит, что такой объект может стоять слева от знака присвоения, и ему может быть таким образом присвоено значение. Принадлежность к l-value означает, что у объекта имеется адрес, и не более того.



Что касается вышеприведенного кода присвоения строки, то он не будет компилироваться потому, что синтаксический анализатор языка C++ запрещает использование таких конструкций. Причем он опирается не на тупую эвристику "слева от знака равно должно быть l-value", а на другие более обширные правила.


Тут возникает вопрос: а как выглядит сущность, которая не имеет адреса? То есть, как выглядит r-value? Вот примеры:



  • Какое-то число (числовой литерал). Ведь нальзя написать так:

  • 250=a+b;


  • Результат вычисления математического выражения. Можно ли что-то присвоить выражению (a+100), например так:

  • (a+100)=500;


    нет, нельзя.


  • Результат вызова функции. То же самое, нельзя написать:

  • sin(alfa)=1.5;


  • Взятие адреса переменной. Ведь нельзя взять адрес переменной, а потом сказать - при получении адреса у меня получился другой адрес!


&variableName=0x123456789



Во всех этих примерах слева от знака равно написана сущность, которая может не иметь адреса. А если может не иметь адреса, значит это r-value. Не очень точно, но можно сказать, что результату работы выражения r-value может не потребоваться память, например потому что результат может быть размещен в регистре. То есть, у такой сущности невозможно получить адрес в памяти.


Примерно так следует воспринимать разницу между выражениями l-value и r-value.


Так же в этом разделе:
 
MyTetra Share v.0.59
Яндекс индекс цитирования