C++ 11 中的POD
POD 是英文中Plain Old Data 的縮寫,意如其名。 Plain 表示了POD 是普通的類型, C++中常見的類型都是這樣的屬性,而不像一些存在著虛函數虛繼承的類型那么特別。 Old 則體現其和C 的兼容性。 比如可以用古老的memcpy() 函數進行復制, 使用memset()進行初始化等。
使用POD 有以下幾個好處:
1. 字節賦值, 可以安全地使用memset 和memcpy對POD 進行初始化和拷貝等操作。
2. 提供對C內存布局兼容,C++ 程序可以與C函數進行相互操作,因為POD 的類型的數據在C和C++間操作總是安全的
3. 保證了靜態初始化的安全有效。 靜態初始化在很多時候能夠提升程序的性能,而POD 類型的對象初始化往往簡單(比如放在目標文件的.bss 段,在初始化中直接賦0)。
在C++ 11 中,對POD 劃分為兩個概念的集合, 即: 平凡的(Trivial) 和標準布局的。
通常情況下, 一個平凡的類或結構體應該符合以下定義
平凡的默認構造函數就是說構造函數什么都不干, 通常情況下, 不定義類的構造函數,編譯器會為我們生產一個平凡的默認構造函數,而一旦定義了構造函數,即使構造函數不包含參數,函數提里面沒有任何代碼,那么該構造函數也就不再是 ‘平凡的‘。 比如:
struct NonTrivial {Nontrivial() {} };? 也可以使用=default關鍵字顯式申明缺省的版本的構造函數,使其’平凡化‘。
2. 擁有平凡?的拷貝構造函數(trivial copy constructor)和移動構造函數(trivial move constructor). 平凡的拷貝構造函數基本上等同于使用memcpy進行類型的構造。同樣地,也可使用=default申明默認的拷貝構造函數。平凡的移動構造函數和平凡的拷貝構造函數類似,只不是用于移動語義。
?
3. 擁有平凡的拷貝賦值運算符(trivial assignment operator) 和移動賦值運算符(Trivial move operator),基本上與平凡的拷貝構造函數和平凡的移動構造函數運算符類似。
4. 不能包含虛函數和虛繼承
在C++ 11 中,可以使用輔助類模版類判斷一個類或結構體是不是平凡的
template <typename T> struct std::is_trivial;
類is_trivial 的成員value 可以用于判斷類型T 是不是平凡的類型。下面的代碼總結了這四種情況:
#include <iostream> #include <type_traits>using namespace std;struct Trivial1 { }; struct Trivial2 { public: int a; private:int b; };struct Trivial3{Trivial1 a;Trivial2 b; };struct Trivial4{Trivial2 a[20]; };struct Trivial5{int x;static int y; };struct NonTrivial1{NonTrivial1() : z(42){}int z; };struct NonTrivial2{NonTrivial2(){}int w;};struct NonTrivial3 {Trivial5 c;virtual void f(){} };int main(int argc, char* argv[]) {cout << is_trivial<Trivial1>::value << endl; //1cout << is_trivial<Trivial2>::value << endl; //1cout << is_trivial<Trivial3>::value << endl; //1cout << is_trivial<Trivial4>::value << endl; //1cout << is_trivial<Trivial5>::value << endl; //1cout << is_trivial<NonTrivial1>::value << endl; //0cout << is_trivial<NonTrivial2>::value << endl; //0cout << is_trivial<NonTrivial3>::value << endl; //0return 0; }?POD 包含的另外一個概念是標準布局, 標準布局的類或結構體應該符合以下的定義:
1. 所有非靜態成員有相同的訪問權限(Public, protected, private)
2. 在類或結構體繼承時,滿足一下兩種情況之一
a. 派生類中有非靜態成員,且只有一個僅包含靜態成員的基類
b. 基類有非靜態成員,而派生類沒有非靜態成員
這樣的類或結構體是標準布局的,比如下面的例子:
struct B1 { static int a; } ; struct D1 : B1 { int d; };struct B2 { int a; }; struct D2 : B2 { static int d; };struct D3 : B2, B1 { static int d; }; struct D4 : B2 { int d; }; struct D5: B2, D1 { };
? D1, D2, D3都是標準布局的, D4,D5則不屬于標準布局,這實際上使得非靜態成員只要同時出現在基類或者派生類中, 其即屬于非標準布局,而多重繼承也會導致類型布局的一些變化,所以一旦非靜態成員出現在多個基類中,派生類也不屬于標準布局
3. 類中的第一個非靜態成員的類型與其基類相同
struct A : B { B b; };
? 這樣的情況A 就不是一個標準布局,而如下例子:
struct A:B {int a; B b; };?則是一個標準布局
4. 沒有虛函數和虛繼承
5. 所有非靜態數據成員均符合標準布局類型,其基類也符合標準布局。
同樣,在C++11 中,可以使用模版類is_standard_layout 來判斷一個類是不是標準布局的
template <typename T> struct std::is_standard_layout
通過is_standard_layout 模版類的成員 value, 可以判斷出其實不是標準布局。
#include <iostream> #include <type_traits> using namespace std; struct SLayout1 {}; struct SLayout2 { private:int a;int b; };struct SLayout3 : SLayout1 {int a;int b;void f(){} };struct SLayout4 : SLayout1 {int a;SLayout1 b; };struct SLayout5 : SLayout1, SLayout3 { };struct SLayout6 { static int a; };struct SLayout7 :SLayout6 { int a; };struct NonSLayout1 : SLayout1{ SLayout1 a; int i; }; struct NonSLayout2 : SLayout2{ int c; }; struct NonSLayout3 : NonSLayout2 {}; struct NonSLayout4 { public: int a; private:int b; };int main(int argc, char* argv[]) {cout << "Is Standard layout:" << endl;cout << is_standard_layout<SLayout1>::value << endl; //1cout << is_standard_layout<SLayout2>::value << endl; //1cout << is_standard_layout<SLayout3>::value << endl; //1cout << is_standard_layout<SLayout4>::value << endl; //1cout << is_standard_layout<SLayout5>::value << endl; //1cout << is_standard_layout<SLayout6>::value << endl; //1cout << is_standard_layout<SLayout7>::value << endl; //1cout << is_standard_layout<NonSLayout1>::value << endl; //0cout << is_standard_layout<NonSLayout2>::value << endl; //0cout << is_standard_layout<NonSLayout3>::value << endl; //0return 0; }? 同樣,要判斷一個類型是不是POD, 標準庫中的<type_traits> 頭文件提供了如下模版類:
template<typename T> struct std::is_pod;
可以使用std::is_pod<T>::value 來判斷一個類型是不是POD。
轉載于:https://www.cnblogs.com/zhouminliang/p/3357073.html
總結
以上是生活随笔為你收集整理的C++ 11 中的POD的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ubuntu下搭建eclipse+tom
- 下一篇: 零基础学习Linux(三)linux与w