命名空间
变体
操作

标识符

来自 cppreference.cn
< cpp‎ | 语言
 
 
C++ 语言
表达式
替代表示
字面量
布尔字面量 - 整数字面量 - 浮点字面量
字符字面量 - 字符串字面量 - nullptr (C++11)
用户定义 (C++11)
工具
属性 (C++11)
类型
typedef 声明
类型别名声明 (C++11)
类型转换
内存分配
类特有的函数属性
explicit (C++11)
static

特殊成员函数
模板
杂项
 
 

一个 标识符 是由任意长度的数字、下划线、小写和大写拉丁字母,以及大多数 Unicode 字符组成的序列。

一个有效标识符的第一个字符必须是以下之一

  • 大写拉丁字母 A-Z
  • 小写拉丁字母 a-z
  • 下划线
  • 任何具有 Unicode 属性 XID_Start 的 Unicode 字符

一个有效标识符的任何其他字符必须是以下之一

  • 数字 0-9
  • 大写拉丁字母 A-Z
  • 小写拉丁字母 a-z
  • 下划线
  • 任何具有 Unicode 属性 XID_Continue 的 Unicode 字符

具有属性 XID_Start 和 XID_Continue 的字符列表可在 DerivedCoreProperties.txt 中找到。

标识符区分大小写(小写字母和大写字母不同),且每个字符都具有意义。每个标识符必须符合 规范化形式 C

注意:大多数实现对 Unicode 标识符的支持是有限的,例如 gcc(直到 10 版)

目录

[编辑] 在声明中

标识符可以用于命名对象、引用、函数、枚举器、类型、类成员、命名空间、模板、模板特化,参数包(C++11 起)、goto 标签以及其他实体,但有以下例外:

  • 关键字标识符不能用于其他目的。
  • 它们唯一可以作为非关键字使用的地方是 attribute-token 中(例如,[[private]] 是一个有效的属性)。
(C++11 起)
  • 具有特殊含义的标识符(finalimportmodule(C++20 起)override)在特定上下文中明确使用,而非作为常规标识符。
    • 除非另有说明,如果给定的标识符是否具有特殊含义存在歧义,则将其解释为常规标识符。
(C++11 起)
  • 以下形式的标识符 (以 token 或预处理 token 形式出现,即不在 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++ 标准库中删除。它们列在 僵尸名称列表 中。

然而,这些标识符在特定上下文中仍为之前的标准化所保留。已删除的成员函数名不能用作函数式宏的名称,而其他已删除的成员名不能用作可移植代码中对象式宏的名称。

[编辑] 在表达式中

命名变量、函数、概念的特化(C++20 起)或枚举器的标识符可以用作表达式。仅由标识符组成的表达式的结果是标识符命名的实体。表达式的值类别lvalue,如果标识符命名的是函数、变量模板参数对象(C++20 起)或数据成员,否则为 rvalue(C++11 前)prvalue(C++11 起)(例如,枚举器rvalue(C++11 前)prvalue(C++11 起)表达式,概念的特化是布尔 prvalue(C++20 起))。

[编辑] 类型

标识符表达式的类型与其所命名实体的类型相同。

存在以下例外情况:

  • 如果(非限定)标识符命名的实体是局部实体,并且如果它在标识符出现的声明区域中未求值操作数之外被命名,将导致一个中间的lambda 表达式通过复制捕获它,那么表达式的类型是类成员访问表达式的类型,该表达式命名将在最内层此中间 lambda 表达式的闭包对象中声明的非静态数据成员。
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&
    };
}
  • 如果命名的实体是类型为 T 的模板参数的模板参数对象,则表达式的类型是 const T
(C++20 起)
(C++11 起)

[编辑] 非限定标识符

除了适当声明的标识符外,以下内容可以在表达式中扮演相同的角色:

(C++11 起)
  • 后跟其参数列表的模板名称,例如 MyTemplate<int>
  • 字符 ~ 后跟类名称,例如 ~MyClass
  • 字符 ~ 后跟 decltype 说明符,例如 ~decltype(str)
(C++11 起)
(C++26 起)

它们与标识符一起被称为 非限定标识符表达式

[编辑] 限定标识符

一个 限定标识符表达式 是一个非限定标识符表达式,在其前面加上作用域解析运算符 ::,并且可选地,由作用域解析运算符分隔的以下任何序列:

  • 命名空间名称;
  • 类名称;
(C++11 起)
(C++26 起)

例如,表达式 std::string::npos 是一个表达式,它命名命名空间 std 中类 string 中的静态成员 npos。表达式 ::tolower 命名全局命名空间中的函数 tolower。表达式 ::std::cout 命名命名空间 std 中的全局变量 cout,它是一个顶层命名空间。表达式 boost::signals2::connection 命名在命名空间 signals2 中声明的类型 connection,而 signals2 声明在命名空间 boost 中。

关键字 template 可能出现在限定标识符中,以消除依赖模板名称的歧义。

有关限定标识符名称查找的详细信息,请参阅限定查找

[编辑] 隐式成员访问转换

如果标识符表达式 E 表示类 C 的某个非静态非类型成员,并且满足以下所有条件,则 E 被转换为类成员访问表达式 this->E

  • E 可能被求值
  • CE 处最内层的 enclosing class。
  • CE 处最内层 enclosing class 的基类。

此转换不适用于模板定义上下文(请参见依赖名称)。

struct X
{
    int x;
};
 
struct B
{
    int b;
};
 
struct D : B
{
    X d;
 
    void func()
    {
        d;   // OK, will be transformed into this->d
        b;   // OK, will be transformed into this->b
        x;   // Error: this->x is ill-formed
 
        d.x; // OK, will be transformed into this->d.x
             // instead of d.this->x or this->d.this->x
    }
};

[编辑] 名称

一个 名称 是以下之一用来指代实体的用法:

  • 标识符
  • 函数表示法中的重载运算符名称(operator+operator new
  • 用户定义转换函数名称(operator bool
  • 用户定义字面量运算符名称(operator ""_km
(C++11 起)
  • 后跟其参数列表的模板名称(MyTemplate<int>

每个名称都通过声明引入程序。在多个翻译单元中使用的名称可能指代相同或不同的实体,具体取决于链接

当编译器在程序中遇到未知名称时,它通过名称查找将其与引入该名称的声明关联起来,但模板声明和定义中的依赖名称除外(对于这些名称,编译器确定它们是命名类型、模板还是其他实体,这可能需要显式消歧)。

[编辑] 缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告 应用于 发布时的行为 正确的行为
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 文档 关于 标识符