Spec-Zone.ru › C++

Идентификаторы

Идентификатор — это произвольная последовательность цифр, символов подчёркивания, строчных и прописных латинских букв и большинства символов Юникода.

Первый символ допустимого идентификатора должен быть одним из следующих:

  • прописные латинские буквы A-Z
  • строчные латинские буквы a-z
  • символ подчёркивания
  • любой символ Юникода с свойством Юникода XID_Start

Любой другой символ допустимого идентификатора должен быть одним из следующих:

  • цифры 0-9
  • прописные латинские буквы A-Z
  • строчные латинские буквы a-z
  • символ подчёркивания
  • любой символ Юникода с свойством Юникода XID_Continue

Список символов со свойствами XID_Start и XID_Continue можно найти в файле DerivedCoreProperties.txt.

Идентификаторы чувствительны к регистру (строчные и прописные буквы различаются), и каждый символ имеет значение. Каждый идентификатор должен соответствовать Нормальной форме C.

Примечание: Поддержка идентификаторов Юникода ограничена в большинстве реализаций, например, gcc (до версии 10).

В объявлениях

Идентификатор может быть использован для именования объектов, ссылок, функций, перечислений, типов, членов класса, пространств имён, шаблонов, специализаций шаблонов, пакетов параметров(с C++11) меток goto и других сущностей, с указанными исключениями:

  • идентификаторы, являющиеся ключевыми словами, не могут быть использованы для других целей;
  • Единственное место, где они могут использоваться как неключевые слова, — это в токене атрибута (например, [[private]] — это допустимый атрибут).
(с C++11)
  • идентификаторы, являющиеся альтернативными представлениями для определённых операторов и знаков препинания, не могут быть использованы для других целей;
  • идентификаторы со специальным значением (final, import, module(с C++20) и override) используются явно в определённом контексте, а не как обычные идентификаторы;
    • Если не указано иное, любая неоднозначность в отношении того, имеет ли данный идентификатор специальное значение, разрешается в пользу интерпретации токена как обычного идентификатора.
(с C++11)
  • Идентификаторы представленные в виде токена или препроцессорного токена (т.е., не в строковой литерале пользователя вроде operator ""id)(с C++11) одной из следующих форм зарезервированы:
    • идентификаторы с двумя символами подчёркивания;
    • идентификаторы, начинающиеся с символа подчёркивания, за которым следует заглавная буква;
    • в глобальном пространстве имён, идентификаторы, начинающиеся с символа подчёркивания.
  • В операторах-литералах:
    • идентификаторы суффикса литералов, которые не начинаются с символа подчёркивания, зарезервированы для будущего стандарта;
    • идентификаторы суффикса литералов, содержащие два символа подчёркивания, зарезервированы для использования реализациями.
(с C++11)

«Зарезервированные» в данном контексте означает, что заголовочные файлы стандартной библиотеки #define или объявляют такие идентификаторы для своих внутренних нужд, компилятор может предварительно определить нестандартные идентификаторы такого рода, а алгоритм привязки имён может предположить, что некоторые из этих идентификаторов не используются. Если программист использует такие идентификаторы, программа некорректна, диагностика не требуется.

Кроме того, определение или #undef определённых имён в единице трансляции является неопределённым поведением, см. зарезервированные имена макросов для получения дополнительной информации.

Мёртвые идентификаторы

Начиная с C++14, некоторые идентификаторы удалены из стандартной библиотеки C++. Они перечислены в списке мёртвых имён.

Однако эти идентификаторы по-прежнему зарезервированы для предыдущих стандартов в определённом контексте. Удалённые имена функций-членов не могут использоваться как имя функций-макросов, а другие удалённые имена-члены не могут использоваться как имя макросов-объектов в переносимом коде.

В выражениях

Идентификатор, имя переменной, функции, специализации концепции,(с C++20) или перечисления может быть использован как выражение. Результат выражения, состоящего только из идентификатора, — это сущность, именованная этим идентификатором. Категория значения выражения — lvalue, если идентификатор именовал функцию, переменную, объект шаблона-параметра(с C++20) или член данных, и rvalue(до C++11)prvalue(с C++11) в противном случае (например, перечисление является rvalue(до C++11)prvalue(с C++11) выражением, специализация концепции — логическое prvalue(с C++20)). Тип выражения определяется следующим образом:

  • Если сущность, именованная (неквалифицированным) идентификатором, является локальной сущностью и привела бы к промежуточному лямбда-выражению, захватив её по значению, если бы она была названа вне области невычисляемого операнда в декларативной области, в которой появляется идентификатор, то тип выражения — тип выражения доступа к члену класса, называющего нестатический член данных, который был бы объявлен для такого захвата в объекте замыкания наиболее вложенного такого промежуточного лямбда-выражения.
void f()
{
    float x, &r = x;
 
    [=]
    {
        decltype(x) y1;        // y1 has type float
        decltype((x)) y2 = y1; // y2 has type float const& because this lambda
                               // is not mutable and x is an lvalue
        decltype(r) r1 = y1;   // r1 has type float&
        decltype((r)) r2 = y2; // r2 has type float const&
    };
}
(с C++11)
  • Если названный объект — параметр шаблона для параметра шаблона типа T, тип выражения — const T.
(с C++20)
  • В противном случае тип выражения такой же, как тип сущности.

В теле нестатической функции-члена каждый идентификатор, обозначающий нестатический член, неявно преобразуется в выражение доступа к члену класса this->member.

Неквалифицированные идентификаторы

Помимо надлежащим образом объявленных идентификаторов, в выражениях в той же роли могут использоваться:

  • имя перегруженного оператора в функционной нотации, например, operator+ или operator new;
  • имя функции-конвертора пользовательского определения, например, operator bool;
  • имя оператора-литерала пользовательского определения, например, operator "" _km;
(с C++11)
  • имя шаблона, за которым следует список его аргументов, например, MyTemplate<int>;
  • символ ~ и за ним имя класса, например, ~MyClass;
  • символ ~ и за ним спецификатор decltype, например, ~decltype(str).
(с C++11)
  • символ ~ и за ним спецификатор индексирования пакетов, например, ~pack...[0].
(с C++26)

Вместе с идентификаторами они известны как неквалифицированные выражения id.

Квалифицированные идентификаторы

Квалифицированное выражение id — это неквалифицированное выражение id, помещённое перед оператором разрешения области видимости ::, и, необязательно, последовательность любого из следующих элементов, разделённых операторами разрешения области видимости:

  • имя пространства имён;
  • имя класса;
  • имя перечисления;
  • спецификатор decltype, обозначающий тип класса или перечисления.
(с C++11)
  • спецификатор индексирования упаковок, обозначающий тип класса или перечисления.
(с C++26)

Например, выражение std::string::npos — это выражение, которое называет статический член npos в классе string в пространстве имён std. Выражение ::tolower называет функцию tolower в глобальном пространстве имён. Выражение ::std::cout называет глобальную переменную cout в пространстве имён std, которое является пространством имён верхнего уровня. Выражение boost::signals2::connection называет тип connection объявленный в пространстве имён signals2, который объявлен в пространстве имён boost.

Ключевое слово template может появляться в квалифицированных идентификаторах по мере необходимости для устранения неоднозначности имен зависимых шаблонов.

Подробности поиска имен для квалифицированных идентификаторов см. в разделе квалифицированного поиска.

Имена

Имя — это использование одного из следующих элементов для ссылки на сущность:

  • идентификатор;
  • имя перегруженного оператора в функциональной нотации (operator+, operator new);
  • имя функции пользовательского преобразования (operator bool);
  • имя оператора пользовательской литеральной константы (operator ""_km);
(с C++11)
  • имя шаблона, за которым следует его список аргументов (MyTemplate<int>).

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

Когда компилятор встречает неизвестное имя в программе, он связывает его с объявлением, которое ввело имя посредством поиска имени, за исключением зависимых имён в объявлениях и определениях шаблонов (для этих имён компилятор определяет, называют ли они тип, шаблон или какую-либо другую сущность, что может потребовать явного разъяснения).

Доклады об ошибках

Следующие исправления, изменяющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применено к Поведение, как опубликовано Правильное поведение
CWG 1440 C++11 выражения decltype, предшествующие ::, могли обозначать любой тип могут обозначать только типы классов
или перечислений
CWG 1963 C++11 использования символов, отличных от цифр, не-цифр
и универсальных имен символов, могли быть использованы в идентификаторе
запрещены
CWG 2521 C++11 идентификатор в строковой литеральной константе оператора литерала был зарезервирован как обычно правила отличаются

См. также

C документация для Идентификаторов

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/language/identifiers

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API