POD (程式設計)

Plain old data structure, 縮寫為 POD, 是 C++ 語言的標準中定義的一類資料結構，POD 適用於需要明確的資料底層操作的系統中。POD 通常被用在系統的邊界處，即指不同系統之間只能以底層資料的形式進行互動，系統的高層邏輯不能互相相容。比如當物件的欄位值是從外部資料中構建時，系統還沒有辦法對物件進行語義檢查和解釋，這時就適用 POD 來儲存資料。

定義

POD 型別包括下述 C++ 型別，以及其 cv-qualified 的型別，還有以其為基型別的陣列型別:

標量型別 (scalar type)
POD 類型別 (POD class type)

1.1 標量型別

術語標量型別包括下述 C++ 型別範疇，以及其 cv-qualified 型別:

算術型別 (arithmetic type)
列舉型別 (enumeration type)
指標型別 (pointer type)
指標到成員型別 (pointer-to-member type)

術語算術型別包括下述 C++ 類型範疇:

整數型別 (integral type)
浮點型別 (floating type)

術語整數型別包括下述 C++ 類型範疇:

有符號整數型別 (signed char, short, int, long),
無符號整數型別 (unsigned char, unsigned short, unsigned int, unsigned long),
字元型別 char 與寬字元型別 wchar_t
布林型別 bool。

術語浮點型別包括 C++ 的 float, double, and long double 型別.

術語列舉型別包括各種列舉型別，即命名的常量值 (named constant values) 的集合.

術語指標型別包括下述 C++ 型別範疇:

空指標 pointer-to-void (void *),
物件指標 pointer-to-object 與指向靜態資料成員的指標 pointer-to-static-member-data (都是形如為 T*，其中 T 是物件型別),
函式指標 pointer-to-function 與指向靜態成員函式的指標 pointer-to-static-member-function (都是形如 T (*)(...)，T 是函式的返回值的型別).

術語指標到成員型別包括下述 C++ 型別範疇:

指標到非靜態資料成員 (pointer-to-nonstatic-member-data), 形如 T C::* 表示指向類 C 的型別為 T 的資料成員的指標；
指標到非靜態成員函式 (pointer-to-nonstatic-member-functions), 形如 T (C::*)(...) 表示指向類 C 的返回值型別為 T 的成員函式的指標.

1.2 POD 類型別

POD 類型別是指聚合類 (aggregate classes, 即 POD-struct types) 與聚合 union (POD-union types)，且不具有下述成員:

指標到成員型別的非靜態資料成員 (包括陣列)。
非 POD 類型別的非靜態資料成員 (包括陣列)。
引用型別的 (reference type) 非靜態資料成員。
使用者定義的複製與賦值運算元。
使用者定義的解構函式。

術語聚合是指任何的陣列或者類，且不具有下述特徵:

使用者定義的建構函式。
私有或保護的非靜態資料成員。
基類。
虛擬函式。

可見，POD 類型別就是指 class、struct、union，且不具有使用者定義的建構函式、解構函式、複製運算元、賦值運算元；不具有繼承關係，因此沒有基類；不具有虛擬函式，所以就沒有虛表；非靜態資料成員沒有私有或保護屬性的、沒有引用型別的、沒有非 POD 類型別的（即巢狀類都必須是 POD）、沒有指標到成員型別的（因為這個型別內含了 this 指標）。

1.3 C++11

C++11 把情況推廣為兩種：

型別是平凡的（trivial），則可以靜態初始化、可以用 memcpy 直接複製資料而不是必須用 copy 建構函式。其生存期始於它的物件的儲存被定義，無須等到建構函式完成。平凡 class 或結構必須滿足：

有平凡的預設建構函式，可用這樣的預設語法：(SomeConstructor = default;)
有平凡的 copy 與 move 建構函式，可用預設語法.

有平凡的 copy 與 move 運算子，可用預設語法.

有平凡的 destructor，不能是虛擬函式.

建構函式是平凡的，僅當類沒有虛成員函式也沒有虛基類。Copy/move 運算子是平凡的，僅當沒有靜態資料成員。

型別是標準佈局的（standard-layout）意味著它是有序的並且安排其成員兼容於 C 語言。這要求滿足：

沒有虛擬函式
沒有虛基類
所有非靜態資料成員有相同的訪問控制 (public, private, protected)
所有非靜態資料成員，包括在任何基類中的，存在於類繼承體系中的一個類中
上述規則適用於所有基類與類繼承體系中的所有非靜態資料成員
沒有同一型別的基型別被定義為第一個非靜態資料成員

一個 class/struct/union 是 POD，當它是平凡的、標準佈局的，所有資料成員是 POD.

分為兩個概念，物件可以不滿足其中一個但是滿足另外一個。例如，類有複雜的 move 與 copy 建構函式，因此不是平凡的，但可能是標準佈局因此能與 C 程式互操作。類似地，一個類的有 public 與 private 的非靜態資料成員，因此不是標準佈局，但可以是平凡的因此可以 memcpy 操作。

用途

POD 型別在原始碼兼容於 ANSI C 時非常重要。POD 物件與 C 語言的對應物件具有共同的一些特性，包括初始化、複製、記憶體佈局、定址。

一個例子是下述 C++ 的 new 表示式中的物件初始化，POD 與 non-POD 的區別:

因此，non-POD 型別的物件或陣列總是被初始化；而 POD 型別的物件或陣列可能未被初始化.

其它與 POD 相關的 C++ 特性:

記憶體佈局 ——POD 物件的組成位元組是連續的.

"POD-struct ... types are layout-compatible if they have the same number of members, and corresponding members (in order) have layout-compatible types".

POD-union ... types are layout-compatible if they have the same number of members, and corresponding members (in any order) have layout-compatible types".

初始化 —— 對於 non-const POD 物件，如果沒有初始化宣告時，具有不確定的初值 (indeterminate initial value) . POD 物件的預設初始化為 0 值。靜態 POD 物件初始化為給定的初值，如果是區域性靜態 POD 物件，在進入所在作用域之前初始化 §6.7, ¶4; 對於非區域性靜態 POD 物件，在任何動態初始化之前賦予初值.

複製 ——POD 物件可直接複製 (例如用 memcpy ) 到其它字元陣列或相同 POD 型別的物件，保持其值不變。POD 型別可以用作標準模板字串類的字元。由於這個原因，函式的返回值如果是 non-POD 型別，則不能透過暫存器傳遞函式的返回值。
定址 —— 一個 POD 物件的地址可以是一個地址常量表達式；一個對 POD 成員的引用可以是一個引用常量表達式。一個 POD-struct 物件的指標，適合用 reinterpret_cast 轉換到它的初始值.

POD JAVA

JAVA 中，一些開發者認為 POD 型別是符合沒有 public 成員且沒有方法的類，比如 data transfer object。其實不使用事件控制代碼並且不實現除 getter 和 setter 之外的附加方法的 POJO（只含有 getter 和 setter 的類）和 JAVA Bean 也屬於 POD。但不管怎麼樣，POJO 和 JAVA Bean 已經有了封裝，已經違反了 POD 的定義了。