Идентификаторы
Идентификатор — это произвольная последовательность цифр, символов подчёркивания, строчных и прописных латинских букв и большинства символов Юникода.
Первый символ допустимого идентификатора должен быть одним из следующих:
- прописные латинские буквы 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 и других сущностей, с указанными исключениями:
- идентификаторы, являющиеся ключевыми словами, не могут быть использованы для других целей;
| (с C++11) |
- идентификаторы, являющиеся альтернативными представлениями для определённых операторов и знаков препинания, не могут быть использованы для других целей;
| (с 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) |
| (с C++20) |
- В противном случае тип выражения такой же, как тип сущности.
В теле нестатической функции-члена каждый идентификатор, обозначающий нестатический член, неявно преобразуется в выражение доступа к члену класса this->member.
Неквалифицированные идентификаторы
Помимо надлежащим образом объявленных идентификаторов, в выражениях в той же роли могут использоваться:
- имя перегруженного оператора в функционной нотации, например,
operator+илиoperator new; - имя функции-конвертора пользовательского определения, например,
operator bool;
| (с C++11) |
- имя шаблона, за которым следует список его аргументов, например,
MyTemplate<int>; - символ
~и за ним имя класса, например,~MyClass;
| (с C++11) |
| (с C++26) |
Вместе с идентификаторами они известны как неквалифицированные выражения id.
Квалифицированные идентификаторы
Квалифицированное выражение id — это неквалифицированное выражение id, помещённое перед оператором разрешения области видимости ::, и, необязательно, последовательность любого из следующих элементов, разделённых операторами разрешения области видимости:
- имя пространства имён;
- имя класса;
| (с 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);
| (с 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