[英]trivial vs. standard layout vs. POD
通俗地說,平凡類型、標准布局類型和 POD 之間有什么區別?
具體來說,我想確定new T
是否與new T()
對於任何模板參數T
。 我應該選擇is_trivial
、 is_standard_layout
和is_pod
哪一個類型特征?
(作為一個附帶問題,可以在沒有編譯器魔法的情況下實現這些類型特征中的任何一個嗎?)
我不認為它可以用真正外行的術語來完成,至少沒有很多額外的解釋。 一個重點是靜態與動態初始化,但向外行解釋這本身就是幾頁......
POD 是在 C++98 中(錯誤)定義的。 確實涉及兩個獨立的意圖,都沒有很好地表達:1)如果您在 C++ 中編譯 C 結構聲明,您得到的應該與您在 C 中擁有的相同。2)POD 只需要/使用靜態(非動態)初始化。
C++0x/11(幾乎)完全放棄了“POD”名稱,轉而支持“平凡”和“標准布局”。 標准布局旨在捕捉第一個意圖——創建與您在 C 中獲得的布局相同的內容。瑣碎旨在捕捉對靜態初始化的支持。
由於new T
與new T()
處理初始化,您可能需要is_trivial
。
我不確定是否需要編譯器魔法。 我的直接反應可能是肯定的,但知道人們用 TMP 做過的一些事情,我很難確定有人也不能這樣做......
編輯:例如,也許最好只引用 N3290 的示例:
struct N { // neither trivial nor standard-layout
int i;
int j;
virtual ~N();
};
struct T { // trivial but not standard-layout
int i;
private:
int j;
};
struct SL { // standard-layout but not trivial
int i;
int j;
~SL();
};
struct POD { // both trivial and standard-layout
int i;
int j;
};
毫無疑問,您可以猜到, POD
也是一個 POD 結構。
對於 POD 類型new T()
是值初始化(將對所有成員進行值初始化),而new T
不會初始化成員(默認初始化)。 有關不同形式的初始化之間的差異, 請參閱此問題。 底線:你需要is_pod
。
布局是類、結構或聯合對象的成員在內存中的排列方式。 這可能是連續的或不連續的。通常語言指定布局,但如果有像虛函數、虛擬基類等的東西,那么編譯器可以自由選擇布局,這可能不是連續的。 這導致了幾個問題,我們無法適當地序列化對象或傳遞給用其他語言(如 C)或函數(如 memcopy)編寫的程序,因為我們無法可靠地復制數據,因為它不在連續位置。
為了使編譯器和c++程序能夠支持上述操作,c++為簡單結構和類引入了3個類別。
瑣碎的
如果類或結構遵循以下規則,則它是微不足道的:
如果一個類是微不足道的,那么它的布局是連續的,但可能會有相應的填充,編譯器可以自由選擇布局中成員的順序。 因此,即使我們可以對對象進行內存復制,但如果我們將該對象復制到 C 程序中,也是不可靠的。我們可以在同一個類中使用不同的訪問說明符,如果使用參數化構造函數,顯然我們必須指定默認構造函數。 但是如果你想讓這個類保持簡單,那么你應該明確地將構造函數設為默認值。構造函數應該是公共的。
標准布局
標准布局定義明確,可以可靠地進行內存復制並適當地傳遞給 C 程序。 此外,標准布局函數可以具有用戶定義的特殊成員函數,如構造函數和析構函數。
POD(普通舊數據)
如果一個類或結構既是平凡的又是標准的布局,那么它被稱為 POD。每個成員都按照聲明對象時指定的順序存儲。 POD 類應該具有 POD 非靜態數據成員。POD 類可以可靠地復制或傳遞給 C 程序。
C++ 程序的類是平凡的、標准的布局,因此是 POD。
#include<iostream>
#include<type_traits>
class xyz
{
public:
int a;
int b;
xyz() = default;
xyz(int x, int y) :a(x), b(y) {}
};
int main() {
std::cout << std::is_trivial<xyz>() << std::endl;//true
std::cout << std::is_standard_layout<xyz>() << std::endl;//true
std::cout << std::is_pod<xyz>() << std::endl;//true
}
文字類型
對於文字類型,可以在編譯時確定布局。文字類型的示例是 void、標量類型(例如 int 、 float 等)、引用、void 數組、標量類型或引用以及具有簡單析構函數的類,以及一個或多個不是移動或復制構造函數的 constexpr 構造函數。 此外,它的所有非靜態數據成員和基類必須是文字類型而不是 volatile
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.