命名空间
变体
操作

类型

来自 cppreference.cn
< cpp‎ | language
 
 
C++ 语言
通用主题
流程控制
条件执行语句
if
迭代语句 (循环)
for
范围 for (C++11)
跳转语句
函数
函数声明
Lambda 函数表达式
inline 说明符
动态异常规范 (在 C++17* 中已弃用)
noexcept 说明符 (C++11)
异常
命名空间
类型
说明符
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
存储期说明符
初始化
 
 

对象引用函数(包括函数模板特化)和表达式都拥有一个称为类型的属性,它既约束了对这些实体允许的操作,又为原本通用的位序列提供了语义含义。

目录

[编辑] 类型分类

C++ 类型系统由下列类型构成

(自 C++11 起)
  • 类型 bool
  • 字符类型
  • 窄字符类型
  • 普通字符类型:charsigned charunsigned char[1]
  • 类型 char8_t
(自 C++20 起)
  • 宽字符类型:char16_tchar32_t(自 C++11 起)wchar_t
  • 带符号整数类型
  • 标准带符号整数类型:signed charshortintlonglong long
  • 扩展带符号整数类型(实现定义);
(自 C++11 起)
  • 无符号整数类型
  • 标准无符号整数类型:unsigned charunsigned shortunsignedunsigned longunsigned long long
  • 扩展无符号整数类型(每个都与一个扩展带符号整数类型相对应,反之亦然);
(自 C++11 起)
  • 标准浮点类型:floatdoublelong double 及其 cv 限定版本
(自 C++23 起)
  • 到对象类型的左值引用;
  • 到函数类型的左值引用;
  • 到对象类型的右值引用;
  • 到函数类型的右值引用;
(自 C++11 起)
(自 C++11 起)
  1. signed charunsigned char 是窄字符类型,但它们不是字符类型。换句话说,窄字符类型的集合不是字符类型的集合的子集。

对于除引用和函数之外的每个非 cv 限定类型,类型系统支持该类型的三个附加 cv 限定版本constvolatileconst volatile)。

[编辑] 其他类别

对象类型(亦见 std::is_object)是(可能 cv 限定的)类型,它不是函数类型、不是引用类型,也不是(可能 cv 限定的)void

下列类型统称为标量类型(亦见 std::is_scalar

(自 C++11 起)
  • 这些类型的 cv 限定版本

下列类型统称为隐式生存期类型

下列类型统称为可平凡复制类型

下列类型统称为标准布局类型

(自 C++11 起)

类型特征层级图

cpp types v3.svg

注意:SVG 图像的元素是可点击的,但你必须先在新浏览器标签页中打开图表

[编辑] 已弃用的类别

下列类型统称为 POD 类型(亦见 std::is_pod

  • 标量类型
  • POD 类
  • 此类类型的数组
  • 这些类型的 cv 限定版本
(在 C++20 中已弃用)

下列类型统称为平凡类型(亦见 std::is_trivial

  • 标量类型
  • 平凡类类型
  • 此类类型的数组
  • 这些类型的 cv 限定版本
(自 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

声明文法的 声明符 部分,在移除名字后,被称为 抽象声明符

类型标识可以在下列情形中使用

(直至 C++17)

类型标识可以在下列情形中经修改后使用

  • 函数 的形参列表中(当省略形参名时),类型标识使用 声明符序列 而非 类型说明符序列(特别地,允许一些存储类说明符);
  • 用户定义的转换函数 的名字中,抽象声明符不能包含函数或数组运算符。

[编辑] 详述类型说明符

详述类型说明符可以用于指代先前声明的类名(类、结构体或联合体)或先前声明的枚举名,即使该名字被非类型声明隐藏。它们也可以用于声明新的类名。

参见 详述类型说明符 以了解详情。

[编辑] 静态类型

由程序的编译时分析产生的表达式的类型,被称为表达式的静态类型。静态类型在程序执行期间不会改变。

[编辑] 动态类型

如果某个 泛左值表达式 指代一个多态对象,则其最派生对象的类型被称为动态类型。

// 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

对于纯右值表达式,动态类型始终与静态类型相同。

[编辑] 不完整类型

下列类型是不完整类型

  • 类型 void(可能 cv 限定);
  • 不完整定义的对象类型:

所有其他类型都是完整类型。

下列任何上下文都需要类型 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 的未知边界数组”和“NT 的数组”)是不同的类型。

指向或引用未知边界数组的指针或引用的类型永久指向或引用不完整类型。由 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 类型树