Namespaces
Variants

Identifiers

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

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

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

  • прописные латинские буквы 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 и других сущностей, за следующими исключениями:

  • Идентификаторы, которые являются ключевыми словами , не могут использоваться для других целей.
  • Единственное место, где они могут использоваться как неключевые слова — это в attribute-token (например, [ [ private ] ] является допустимым атрибутом ).
(начиная с C++11)
  • Идентификаторы с особым значением ( final , import , module (since C++20) и override ) используются явно в определенном контексте, а не являются обычными идентификаторами.
    • Если не указано иное, любая неоднозначность относительно того, имеет ли данный идентификатор особое значение, разрешается в пользу интерпретации токена как обычного идентификатора.
(since C++11)
  • Идентификаторы которые появляются как токен или токен препроцессора (т.е. не в user-defined-string-literal как operator "" id ) (начиная с C++11) одной из следующих форм являются зарезервированными:
    • в глобальном пространстве имён, идентификаторы, начинающиеся с подчёркивания
    • идентификаторы, содержащие двойное подчёркивание или начинающиеся с подчёркивания за которым следует заглавная буква, за исключением следующих идентификаторов:
(начиная с C++11)
  • следующие макросы, определенные в стандартной библиотеке:
  • макросы совместимости с C __alignas_is_defined и __alignof_is_defined (определены в <stdalign.h> )
  • макрос совместимости с C __bool_true_false_are_defined (определен в <stdbool.h> )
(начиная с 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++20)
(начиная с C++11)

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

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

(since C++11)
  • имя шаблона с последующим списком аргументов, например MyTemplate < int > ;
  • символ ~ с последующим именем класса, например ~MyClass ;
  • символ ~ , за которым следует спецификатор decltype , например ~decltype ( str ) .
(начиная с C++11)
(начиная с C++26)

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

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

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

  • имя пространства имён;
  • имя класса;
  • имя перечисления;
  • спецификатор decltype обозначающий тип класса или перечисления.
(начиная с C++11)
  • спецификатор индексации пакета pack indexing specifier , обозначающий тип класса или перечисления.
(начиная с 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 :

Это преобразование не применяется в контексте определения шаблона (см. 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 )
  • имя пользовательского литерального оператора ( operator "" _km )
(начиная с 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 для Идентификаторов