Страницы

Поиск по вопросам

понедельник, 6 января 2020 г.

Почему строковый литерал в С++ это l-value?

#cpp #строковый_литерал


Например строковый литерал: "Hello, world!" не может стоять слева от оператора присваивания.
Тогда, как он может являться леводопустимым выражением?

"WTF" = "Hello, world!"; // ошибка компиляции



  l-value:
  
  
  Выражения, непосредственно обозначающие объект, non-modifiable в случае const-квалификации.
Например, имя переменной, параметра функции и т.п.
  Выражения ссылочных типов. non-modifiable в случае const-квалификации. В частности,
результат вызова функций, возвращающих объекты по ссылке; выражения, состоящие из имен
ссылочных переменных; операции преобразования к ссылочному типу и т.д.
  Результат встроенной операции разыменования (*) — lvalue указуемого типа; non-modifiable
в случае const-квалификации.
  Результат встроенных префиксных операций ++, --.
  Имя функции.
  Имя массива. 
  Строковые литералы.
  
  
  r-value:
  
  
  Выражения, обозначающие временные объекты. В частности, результат вызова функций,
возвращающих объекты не по ссылке; результат встроенных операций +, -. > *, / и т.п.;
явное создание временной переменной int() или C(); преобразования не к ссылочным типам
и т.д.
  Результат встроенной операции взятия адреса (&) — rvalue типа указатель.
  Результат встроенных постфиксных операций ++, --.
  Литералы, за исключением строковых (например, числовые литералы).
  Константы перечислений.
  

    


Ответы

Ответ 1



Строковый литерал в С++ по всей строгости - это константа, и уже по одному этому участвовать в присвоении не может. Более того, в 2.14.5.12 сказано: The effect of attempting to modify a string literal is undefined. Далее, по сути это - массив, а массив опять же в присвоении ну никак не участвует. В 3.10.9 говорится: "If an expression can be used to modify the object to which it refers, the expression is called modifiable. A program that attempts to modify an object through a nonmodifiable lvalue or rvalue expression is ill-formed." Наш же lvalue явно немодифицируемый. Впрочем, само понятие lvalue имеет несколько иной смысл, чем приписываемый вами. An lvalue (so called, historically, because lvalues could appear on the left-hand side of an assignment expression) designates a function or an object. Тут главное не то, что исторически они могли быть слева в выражении присваивания, а то, что это объект в памяти, от которого можно взять адрес. А получить адрес строкового литерала вполне можно, и в этом смысле это lvalue. По-моему, так... (с) Пух

Ответ 2



lvalue не значит, что такое выражение всегда может стоять слева от оператора присваивания. К примеру, пусть у Вас есть const int meConst = 5;, meConst в выражении meConst = 6; является lvalue, но пример всё равно собрать не удастся, т.к. нельзя изменять const int. То же самое со строковым литералом: да — это lvalue, нет — его нельзя модифицировать. И небольшая, но релевантная цитата из C11[6.3.2.1]: A modifiable lvalue is an lvalue that does not have array type, does not have an incomplete type, does not have a constqualified type, and if it is a structure or union, does not have any member (including, recursively, any member or element of all contained aggregates or unions) with a constqualified type.

Комментариев нет:

Отправить комментарий