类型
对象、引用、函数(包括函数模板特化)和表达式都拥有一个称为类型的属性,它既约束了对这些实体允许的操作,又为原本通用的位序列提供了语义含义。
目录 |
[编辑] 类型分类
C++ 类型系统由下列类型构成
- 类型 void(亦见 std::is_void);
|
(自 C++11 起) |
- 算术类型(亦见 std::is_arithmetic)
- 整型(包含 cv 限定版本,亦见 std::is_integral,整型的一个同义词是整数类型)
- 类型 bool;
- 字符类型
- 窄字符类型
- 普通字符类型:char、signed char、unsigned char[1]
|
(自 C++20 起) |
- 宽字符类型:char16_t、char32_t、(自 C++11 起)wchar_t;
- 带符号整数类型
- 标准带符号整数类型:signed char、short、int、long、long long;
|
(自 C++11 起) |
- 无符号整数类型
- 标准无符号整数类型:unsigned char、unsigned short、unsigned、unsigned long、unsigned long long;
|
(自 C++11 起) |
- 浮点类型(亦见 std::is_floating_point)
- 标准浮点类型:float、double、long double 及其 cv 限定版本;
(自 C++23 起) |
- 复合类型(亦见 std::is_compound)
-
-
- 到对象类型的左值引用;
- 到函数类型的左值引用;
-
|
(自 C++11 起) |
- 指针类型(亦见 std::is_pointer)
- 指向数据成员指针 类型(亦见 std::is_member_object_pointer);
- 指向成员函数指针 类型(亦见 std::is_member_function_pointer);
- 数组类型(亦见 std::is_array);
- 函数类型(亦见 std::is_function);
- 枚举类型(亦见 std::is_enum);
(自 C++11 起) |
- 类类型:
- 非联合体类型(亦见 std::is_class);
- 联合体类型(亦见 std::is_union)。
- ↑ signed char 和 unsigned char 是窄字符类型,但它们不是字符类型。换句话说,窄字符类型的集合不是字符类型的集合的子集。
对于除引用和函数之外的每个非 cv 限定类型,类型系统支持该类型的三个附加 cv 限定版本(const、volatile 和 const volatile)。
[编辑] 其他类别
对象类型(亦见 std::is_object)是(可能 cv 限定的)类型,它不是函数类型、不是引用类型,也不是(可能 cv 限定的)void。
下列类型统称为标量类型(亦见 std::is_scalar)
(自 C++11 起) |
- 这些类型的 cv 限定版本
下列类型统称为隐式生存期类型
- 标量类型
- 隐式生存期类类型
- 数组类型
- 这些类型的 cv 限定版本
下列类型统称为可平凡复制类型
下列类型统称为标准布局类型
|
(自 C++11 起) |
类型特征层级图 |
---|
注意:SVG 图像的元素是可点击的,但你必须先在新浏览器标签页中打开图表 |
[编辑] 已弃用的类别
下列类型统称为 POD 类型(亦见 std::is_pod)
|
(在 C++20 中已弃用) |
下列类型统称为平凡类型(亦见 std::is_trivial)
|
(自 C++11 起) (在 C++26 中已弃用) |
[编辑] 程序定义的类型
程序定义的特化 是一个 显式特化 或 偏特化,它不是 C++ 标准库 的一部分,也不是由实现定义的。
程序定义的类型 是下列类型之一
|
(自 C++11 起) |
- 程序定义的特化的 实例化。
[编辑] 类型命名
可以通过下列方式声明 名字 以指代类型
不具名的类型常常需要在 C++ 程序中被引用;用于此目的的语法被称为 类型标识。命名类型 T
的类型标识的语法,与类型为 T
的变量或函数的声明的语法完全相同,只是标识符被省略,例外是声明文法的 声明符序列 被约束为 类型说明符序列,并且仅当类型标识出现在非模板类型别名声明的右手侧时,才可以定义新类型。
int* p; // declaration of a pointer to int static_cast<int*>(p); // type-id is "int*" int a[3]; // declaration of an array of 3 int new int[3]; // type-id is "int[3]" (called new-type-id) int (*(*x[2])())[3]; // declaration of an array of 2 pointers to functions // returning pointer to array of 3 int new (int (*(*[2])())[3]); // type-id is "int (*(*[2])())[3]" void f(int); // declaration of a function taking int and returning void std::function<void(int)> x = f; // type template parameter is a type-id "void(int)" std::function<auto(int) -> void> y = f; // same std::vector<int> v; // declaration of a vector of int sizeof(std::vector<int>); // type-id is "std::vector<int>" struct { int x; } b; // creates a new type and declares an object b of that type sizeof(struct { int x; }); // error: cannot define new types in a sizeof expression using t = struct { int x; }; // creates a new type and declares t as an alias of that type sizeof(static int); // error: storage class specifiers not part of type-specifier-seq std::function<inline void(int)> f; // error: neither are function specifiers
声明文法的 声明符 部分,在移除名字后,被称为 抽象声明符。
类型标识可以在下列情形中使用
- 在转型表达式中指定目标类型;
- 作为
sizeof
、alignof
、alignas
、new
和typeid
的实参; - 在 类型别名 声明的右手侧;
- 作为 函数 声明的尾随返回类型;
- 作为 模板类型形参 的默认实参;
- 作为 模板类型形参 的模板实参;
|
(直至 C++17) |
类型标识可以在下列情形中经修改后使用
本节不完整 原因:8.2[dcl.ambig.res] 如果可以紧凑地总结 |
本节不完整 原因:提及并链接到 decltype 和 auto |
[编辑] 详述类型说明符
详述类型说明符可以用于指代先前声明的类名(类、结构体或联合体)或先前声明的枚举名,即使该名字被非类型声明隐藏。它们也可以用于声明新的类名。
参见 详述类型说明符 以了解详情。
[编辑] 静态类型
由程序的编译时分析产生的表达式的类型,被称为表达式的静态类型。静态类型在程序执行期间不会改变。
[编辑] 动态类型
如果某个 泛左值表达式 指代一个多态对象,则其最派生对象的类型被称为动态类型。
// given struct B { virtual ~B() {} }; // polymorphic type struct D : B {}; // polymorphic type D d; // most-derived object B* ptr = &d; // the static type of (*ptr) is B // the dynamic type of (*ptr) is D
对于纯右值表达式,动态类型始终与静态类型相同。
[编辑] 不完整类型
下列类型是不完整类型
所有其他类型都是完整类型。
下列任何上下文都需要类型 T
是完整类型
- 返回类型为
T
或形参类型为T
的函数的定义或调用; - 类型为
T
的对象的定义; - 类型为
T
的非静态类数据成员的声明; - 类型为
T
的对象或元素类型为T
的数组的new
表达式; - 应用于类型为
T
的泛左值的左值到右值转换; - 到类型
T
的隐式或显式转换; - 到类型 T* 或 T& 的 标准转换、
dynamic_cast
或static_cast
,除非从空指针常量或从可能 cv 限定的 void 指针转换; - 应用于类型为
T
的表达式的类成员访问运算符; - 应用于类型
T
的typeid
、sizeof
或alignof
运算符; - 应用于指向
T
的指针的算术运算符; - 基类为
T
的类的定义; - 赋值给类型为
T
的左值; - 类型为
T
、T& 或 T* 的处理程序。
(通常,当 T
的大小和布局必须已知时。)
如果这些情形中的任何一种出现在翻译单元中,则类型的定义必须出现在同一翻译单元中。否则,则不是必需的。
一个不完整定义的对象类型可以被完成
- 类类型(例如 class X)可能在一个翻译单元中的某点被视为不完整,而在稍后被视为完整;类型 class X 在这两点是相同的类型
struct X; // declaration of X, no definition provided yet extern X* xp; // xp is a pointer to an incomplete type: // the definition of X is not reachable void foo() { xp++; // ill-formed: X is incomplete } struct X { int i; }; // definition of X X x; // OK: the definition of X is reachable void bar() { xp = &x; // OK: type is “pointer to X” xp++; // OK: X is complete }
- 数组对象的声明类型可能是个不完整类类型的数组,因此是不完整的;如果类类型稍后在翻译单元中被完成,则数组类型变为完整;这两点的数组类型是相同的类型。
- 数组对象的声明类型可能是未知边界数组,因此在一个翻译单元中的某点是不完整的,而在稍后是完整的;这两点的数组类型(“
T
的未知边界数组”和“N 个T
的数组”)是不同的类型。
指向或引用未知边界数组的指针或引用的类型永久指向或引用不完整类型。由 typedef
声明命名的未知边界数组永久指代不完整类型。在任一情况下,数组类型都不能被完成
extern int arr[]; // the type of arr is incomplete typedef int UNKA[]; // UNKA is an incomplete type UNKA* arrp; // arrp is a pointer to an incomplete type UNKA** arrpp; void foo() { arrp++; // error: UNKA is an incomplete type arrpp++; // OK: sizeof UNKA* is known } int arr[10]; // now the type of arr is complete void bar() { arrp = &arr; // OK: qualification conversion (since C++20) arrp++; // error: UNKA cannot be completed }
[编辑] 缺陷报告
下列行为变更缺陷报告被追溯应用到先前发布的 C++ 标准。
DR | 应用于 | 已发布行为 | 正确行为 |
---|---|---|---|
CWG 328 | C++98 | 不禁止不完整类型的类成员 如果从不创建类类型的对象 |
非静态类数据成员 需要是完整类型 |
CWG 977 | C++98 | 枚举类型变为完整类型的点 在其定义中不清晰 |
一旦确定 底层类型,类型即为完整类型 |
CWG 1362 | C++98 | 到类型 T* 或 T& 的用户定义转换 |
需要 T 是完整类型 |
不需要 | C++98 | CWG 2006 | cv 限定的 void 类型是对象类型和完整类型 |
从两个类别中排除 | C++98 | CWG 2448 | 只有 cv 非限定类型可以是整型和浮点类型 |
允许 cv 限定类型 | C++98 | CWG 2630 不清晰类是否在类的定义出现的翻译单元外部被视为完整 |
类是完整类型 如果其定义在此情况下是 可达的 |
CWG 2643 | C++98 | 指向未知边界数组的指针的类型 不能被完成(但它已经是完整类型) |
被指向的数组类型 不能被完成 |
LWG 2139 | C++98 | “用户定义类型”的含义不清晰 | 定义并使用“程序 定义的类型”替代 |
LWG 3119 | C++11 | 不清晰闭包类型是否是程序定义的类型 | 已明确 |
[编辑] 参考文献
- C++23 标准 (ISO/IEC 14882:2024)
- 6.8.2 基本类型 [basic.fundamental]
- C++20 标准 (ISO/IEC 14882:2020)
- 6.8.2 基本类型 [basic.fundamental]
- C++17 标准 (ISO/IEC 14882:2017)
- 6.9.1 基本类型 [basic.fundamental]
- C++14 标准 (ISO/IEC 14882:2014)
- 3.9.1 基本类型 [basic.fundamental]
- C++11 标准 (ISO/IEC 14882:2011)
- 3.9.1 基本类型 [basic.fundamental]
- C++98 标准 (ISO/IEC 14882:1998)
- 3.9.1 基本类型 [basic.fundamental]
[编辑] 参见
类型特征 | 用于查询类型属性的编译时模板接口 |
C 文档 关于 类型
|
[编辑] 外部链接
1. | Howard Hinnant 的 C++0x 类型树 |