Identifiers
Идентификатор — это произвольно длинная последовательность цифр, подчеркиваний, строчных и прописных латинских букв и большинства символов Юникода.
Первый символ допустимого идентификатора должен быть одним из следующих:
- прописные латинские буквы A-Z
- строчные латинские буквы a-z
- символ подчеркивания
- любой символ Юникода со свойством XID_Start
Любой другой символ допустимого идентификатора должен быть одним из следующих:
- цифры 0-9
- заглавные латинские буквы A-Z
- строчные латинские буквы a-z
- символ подчеркивания
- любой символ Юникода со свойством XID_Continue
Списки символов со свойствами XID_Start и XID_Continue можно найти в DerivedCoreProperties.txt .
Идентификаторы чувствительны к регистру (строчные и прописные буквы различаются), и каждый символ имеет значение. Каждый идентификатор должен соответствовать Normalization Form C .
Примечание: Поддержка Unicode-идентификаторов ограничена в большинстве реализаций, например gcc (до версии 10) .
Содержание |
В объявлениях
Идентификатор может использоваться для именования объектов, ссылок, функций, перечислителей, типов, членов классов, пространств имён, шаблонов, специализаций шаблонов, пачек параметров (начиная с C++11) , меток goto и других сущностей, за следующими исключениями:
- Идентификаторы, которые являются ключевыми словами , не могут использоваться для других целей.
|
(начиная с C++11) |
- Идентификаторы, которые являются альтернативными представлениями для определённых операторов и пунктуаторов, не могут использоваться для других целей.
|
(since C++11) |
-
Идентификаторы
которые появляются как токен или токен препроцессора (т.е. не в
user-defined-string-literal
как
operator
""
id
)
(начиная с C++11)
одной из следующих форм являются зарезервированными:
- в глобальном пространстве имён, идентификаторы, начинающиеся с подчёркивания
- идентификаторы, содержащие двойное подчёркивание или начинающиеся с подчёркивания за которым следует заглавная буква, за исключением следующих идентификаторов:
-
-
- predefined macros (включая language feature test macros ) (начиная с C++20)
-
| (начиная с C++11) |
|
(начиная с C++11) |
| (начиная с C++20) |
«Зарезервированными» здесь означается, что заголовки стандартной библиотеки #define или объявляют такие идентификаторы для своих внутренних нужд, компилятор может предопределять нестандартные идентификаторы такого рода, и алгоритм декорирования имён может предполагать, что некоторые из этих идентификаторов не используются. Если программист использует такие идентификаторы, программа является некорректной, диагностика не требуется.
Кроме того, неопределённое поведение возникает при #define или #undef определённых имён в единице трансляции, подробнее см. зарезервированные имена макросов .
Зомби-идентификаторы
Начиная с C++14, некоторые идентификаторы были удалены из стандартной библиотеки C++. Они перечислены в списке zombie names .
Однако эти идентификаторы всё ещё зарезервированы для предыдущей стандартизации в определённом контексте. Удалённые имена функций-членов не могут использоваться в качестве имён для функциональных макросов, а другие удалённые имена членов не могут использоваться в качестве имён для объектных макросов в переносимом коде.
В выражениях
Идентификатор, который называет переменную, функцию, специализацию concept , (since C++20) или перечислитель, может использоваться как expression . Результатом выражения, состоящего только из идентификатора, является сущность, именуемая этим идентификатором. value category выражения является lvalue , если идентификатор называет функцию, переменную , объект template parameter (since C++20) или член данных, и rvalue (until C++11) prvalue (since C++11) в остальных случаях (например, enumerator является rvalue (until C++11) prvalue (since C++11) выражением , специализация concept является bool prvalue (since C++20) ).
Тип
Тип выражения-идентификатора совпадает с типом сущности, которую он обозначает.
|
Существуют следующие исключения:
void f() { float x, &r = x; [=] { decltype(x) y1; // y1 имеет тип float decltype((x)) y2 = y1; // y2 имеет тип float const& потому что эта лямбда // не является mutable и x является lvalue decltype(r) r1 = y1; // r1 имеет тип float& decltype((r)) r2 = y2; // r2 имеет тип float const& }; }
|
(начиная с C++11) |
Неквалифицированные идентификаторы
Помимо соответствующим образом объявленных идентификаторов, в выражениях в той же роли могут использоваться следующие элементы:
- имя перегруженного оператора в функциональной нотации, такое как operator + или operator new ;
- имя пользовательской функции преобразования , такое как operator bool ;
|
(since C++11) |
- имя шаблона с последующим списком аргументов, например MyTemplate < int > ;
- символ ~ с последующим именем класса, например ~MyClass ;
|
(начиная с C++11) |
|
(начиная с C++26) |
Вместе с идентификаторами они известны как выражения неполных идентификаторов .
Квалифицированные идентификаторы
Квалифицированное выражение идентификатора — это неквалифицированное выражение идентификатора, перед которым стоит оператор разрешения области видимости :: , и, опционально, последовательность любого из следующих элементов, разделённых операторами разрешения области видимости:
- имя пространства имён;
- имя класса;
|
(начиная с C++11) |
|
(начиная с C++26) |
Например, выражение std:: string :: npos является выражением, которое обозначает статический член npos в классе string в пространстве имён std . Выражение :: tolower обозначает функцию tolower в глобальном пространстве имён. Выражение :: std:: cout обозначает глобальную переменную cout в пространстве имён std , которое является пространством имён верхнего уровня. Выражение boost :: signals2 :: connection обозначает тип connection объявленный в пространстве имён signals2 , которое объявлено в пространстве имён boost .
Ключевое слово template может появляться в квалифицированных идентификаторах при необходимости для разрешения неоднозначности зависимых шаблонных имён .
См. qualified lookup для подробностей о поиске имен для квалифицированных идентификаторов.
Преобразование неявного доступа к члену
Если идентификаторное выражение
E
обозначает нестатический член-данные некоторого класса
C
и выполняются все следующие условия,
E
преобразуется в выражение доступа к члену класса
this
-
>
E
:
- E не является правым операндом оператора доступа к члену .
- Если E является квалифицированным выражением идентификатора, E не является непомещенным в скобки операндом оператора взятия адреса .
- Выполняется любое из следующих условий:
-
- E является потенциально вычисляемым выражением .
-
Cявляется самым внутренним охватывающим классом в точке E . -
Cявляется базовым классом самого внутреннего охватывающего класса в точке E .
Это преобразование не применяется в контексте определения шаблона (см. dependent names ).
struct X { int x; }; struct B { int b; }; struct D : B { X d; void func() { d; // OK, будет преобразовано в this->d b; // OK, будет преобразовано в this->b x; // Ошибка: this->x некорректно d.x; // OK, будет преобразовано в this->d.x // вместо d.this->x или this->d.this->x } };
Имена
Имя name - это использование одного из следующих вариантов для обращения к сущности:
- идентификатор
- перегруженное имя оператора в функциональной нотации ( operator + , operator new )
- имя пользовательской функции преобразования ( operator bool )
|
(начиная с C++11) |
- имя шаблона, за которым следует список его аргументов ( MyTemplate < int > )
Каждое имя вводится в программу с помощью декларации . Имя, используемое более чем в одной единице трансляции, может ссылаться на одну и ту же или разные сущности, в зависимости от линковки .
Когда компилятор встречает неизвестное имя в программе, он связывает его с объявлением, которое ввело это имя, посредством name lookup , за исключением dependent names в объявлениях и определениях шаблонов (для таких имен компилятор определяет, обозначают ли они тип, шаблон или другую сущность, что может потребовать explicit disambiguation ).
Отчеты о дефектах
Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены задним числом к ранее опубликованным стандартам C++.
| DR | Применяется к | Поведение в опубликованной версии | Корректное поведение |
|---|---|---|---|
| CWG 1440 | C++11 |
выражения decltype, предшествующие
::
могли обозначать любой тип
|
могут обозначать только классы
или перечисления |
| CWG 1963 | C++11 |
символы, определяемые реализацией, кроме цифр, не-цифр
и универсальных символьных имен, могли использоваться в идентификаторах |
запрещено |
| CWG 2521 | C++11 |
идентификатор в
user-defined-string-literal
литерального оператора резервировался как обычно |
правила отличаются |
| CWG 2771 | C++98 | & a не преобразовывался в & this - > a в контекстах классов | преобразуется |
| CWG 2777 | C++20 |
тип выражения-идентификатора был неясен,
если он именует объект параметра шаблона |
прояснено |
| CWG 2818 | C++98 | имена предопределенных макросов зарезервированы | они не зарезервированы |
Смотрите также
|
Документация C
для
Идентификаторов
|