命名空間
變體
動作

類型

出自 cppreference.com
< 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)
儲存期指定符
初始化
 
 

物件參照函式(包含函式樣板特化)以及表達式都具有一種稱為「類型」(type)的屬性,該屬性不僅限制了這些實體所允許的操作,也為原本僅是通用的位元序列提供了語意意義。

目錄

[編輯] 類型分類

C++ 類型系統包含以下類型

(C++11 起)
  • bool 類型;
  • 字元類型
  • 窄字元類型
  • 一般字元類型:char, signed char, unsigned char[1]
  • char8_t 類型
(自 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 起)
  • 標準浮點類型:float, double, long double 以及它們的 cv 限定版本
(自 C++23 起)
  • 物件類型的左值參照;
  • 函式類型的左值參照;
  • 物件類型的右值參照;
  • 函式類型的右值參照;
(C++11 起)
(C++11 起)
  1. signed charunsigned char 是窄字元類型,但它們不是「字元類型」。換句話說,窄字元類型的集合不是字元類型集合的子集。

對於每一種非 cv 限定、且非參照與函式的類型,類型系統支援該類型的三種額外的 cv 限定版本constvolatile 以及 const volatile)。

[編輯] 其他類別

物件類型(參見 std::is_object)是指一種(可能帶有 cv 限定的)類型,它不是函式類型,不是參照類型,也不是(可能帶有 cv 限定的)void

下列類型統稱為「純量類型」(scalar types,參見 std::is_scalar):

(C++11 起)
  • 這些類型的 cv 限定版本

下列類型統稱為「隱式生命週期類型」(implicit-lifetime types):

下列類型統稱為「平凡可複製類型」(trivially copyable types):

下列類型統稱為「標準佈局類型」(standard-layout types):

(C++11 起)

類型特徵層級圖

cpp types v3.svg

注意:SVG 影像中的元素皆可點擊,但您必須先在新瀏覽器分頁中開啟該圖表

[編輯] 已棄用的類別

下列類型統稱為「POD 類型」(參見 std::is_pod):

  • 純量類型
  • POD 類別
  • 此類類型的陣列
  • 這些類型的 cv 限定版本
(C++20 中已棄用)

下列類型統稱為「平凡類型」(trivial types,參見 std::is_trivial):

(C++11 起)
(在 C++26 中棄用)

[編輯] 程式定義類型

「程式定義特化」(program-defined specialization)是指非 C++ 標準函式庫的一部分,且不由實作所定義的顯式特化部分特化

「程式定義類型」(program-defined type)是下列類型之一:

(C++11 起)

[編輯] 類型命名

可以透過下列方式宣告一個指向類型的名稱

C++ 程式中經常需要參照沒有名稱的類型;其語法稱為 type-id。命名類型 Ttype-id 語法,與宣告類型為 T 的變數或函式的宣告語法完全相同(省略識別符),例外之處在於宣告語法中的 decl-specifier-seq 被限制為 type-specifier-seq,且僅在 type-id 出現在非樣板類型別名宣告的右側時,才允許定義新類型。

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

宣告語法中移除名稱後的 declarator(宣告子)部分,稱為 abstract-declarator(抽象宣告子)。

type-id 可用於下列情況:

(直到 C++17)

type-id 在某些修改後,可用於下列情況:

  • 函式的參數列表中(當省略參數名稱時),type-id 使用 decl-specifier-seq 而非 type-specifier-seq(特別是允許某些儲存類別說明符);
  • 使用者自訂轉換函式的名稱中,抽象宣告子不能包含函式或陣列運算子。

[編輯] 詳述類型說明符 (Elaborated type specifier)

詳述類型說明符可用於參照先前宣告的類別名稱(class, struct 或 union)或先前宣告的列舉名稱,即使該名稱已被非類型宣告所隱藏。它們也可用於宣告新的類別名稱。

詳細資訊請參見詳述類型說明符

[編輯] 靜態類型

由編譯時期程式分析所得出的表達式類型,稱為該表達式的「靜態類型」。靜態類型在程式執行期間不會改變。

[編輯] 動態類型

如果某個泛左值表達式參照到一個多型物件,則其「最衍生物件」(most derived object)的類型稱為動態類型。

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

對於純右值 (prvalue) 表達式,其動態類型永遠與靜態類型相同。

[編輯] 不完整類型

下列類型屬於「不完整類型」(incomplete types):

所有其他類型皆為完整類型。

下列任一情境都要求類型 T 必須是完整的:

(通常在必須已知 T 的大小與佈局時。)

如果這些情況中的任何一個出現在轉譯單元 (translation unit) 中,則該類型的定義必須出現在同一個轉譯單元中。否則,則無此要求。

未完整定義的物件類型可以被完成:

  • 類別類型(如 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 為完整類型 不再需要
CWG 2006 C++98 cv 限定的 void 類型曾經是物件類型與完整類型 從這兩個類別中排除
CWG 2448 C++98 僅有非 cv 限定類型可以是整數與浮點類型 允許 cv 限定類型
CWG 2630 C++98 類別在該類別定義出現的轉譯單元之外是否被視為完整
是不明確的
如果類別的定義
在此情況下是可及的,
則該類別是完整的
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 文件 關於 類型 (Type)

[編輯] 外部連結

1.  Howard Hinnant 的 C++0x 類型樹
English Deutsch 日本語 中文(简体) 中文(繁體)