日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++11 POD类型

發布時間:2024/9/21 c/c++ 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++11 POD类型 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
POD,全稱plain old data,plain代表它是一個普通類型,old代表它可以與c兼容,可以使用比如memcpy()這類c中最原始函數進行操作。C++11中把POD分為了兩個基本概念的集合,即:平凡的(trival)和標準布局的(standard layout)。

1、首先是平凡的(trival)定義,通常一個平凡的類或者結構體需要滿足以下定義

  (1).擁有平凡的默認構造函數和析構函數。默認的意思就是由編譯器為我們自動生成的,不許是我們自己定義的,而一旦定義了構造函數,即使函數體里沒有任何代碼,那么該構造函數也不在是平凡的,但是由于c++11提供了default,也可以是自己定義的加=default。

  (2).擁有平凡的拷貝構造函數和移動構造函數。默認的意思同上,也可以使用=default。

  (3).擁有平凡的拷貝賦值運算符和移動賦值運算符。

  (4).不能包含虛函數和虛基類。

C++11中,我們使用模版類std::is_trivial<T>::value來判斷數據類型是否為平凡類型。

#include "stdafx.h" #include <iostream>using namespace std;class A { A(){} }; class B { B(B&){} }; class C { C(C&&){} }; class D { D operator=(D&){} }; class E { E operator=(E&&){} }; class F { ~F(){} }; class G { virtual void foo() = 0; }; class H : G {}; class I {};int _tmain(int argc, _TCHAR* argv[]) {std::cout << std::is_trivial<A>::value << std::endl; //有不平凡的構造函數std::cout << std::is_trivial<B>::value << std::endl; //有不平凡的拷貝構造函數std::cout << std::is_trivial<C>::value << std::endl; //有不平凡的拷貝賦值運算符std::cout << std::is_trivial<D>::value << std::endl; //有不平凡的拷貝賦值運算符std::cout << std::is_trivial<E>::value << std::endl; //有不平凡的移動賦值運算符std::cout << std::is_trivial<F>::value << std::endl; //有不平凡的析構函數std::cout << std::is_trivial<G>::value << std::endl; //有虛函數std::cout << std::is_trivial<H>::value << std::endl; //有虛基類std::cout << std::is_trivial<I>::value << std::endl; //平凡的類return 0; }

?

2.接下來是標準布局的定義

(1).所有非靜態成員擁有相同的訪問級別,(訪問級別就是public,private,protected)

struct t1{ private :int a; public:int b; }; //不滿足標準布局,因為a,b訪問級別不同。

(2).在類和結構體繼承時需要滿足以下兩個情況之一:

  派生類中有非靜態類,那么這個派生類只能有且只有一個僅包含了靜態成員的基類。

  基類有非靜態成員,那么派生類中不允許有非靜態成員。

(這兩句話看著挺繞口,其實就是在說明一個事實,關于非靜態數據的事實,派生類中有非靜態的數據那么它的基類只能是只有靜態的,而且基類只能有一個。如果基類有非靜態的, 那么派生類就不能有非靜態的。有種蹺蹺板的感覺,非靜態的對面坐著的是靜態,父子類就 是坐在蹺蹺板的兩端這種對應關系。)

(3).類中第一個非靜態類型與基類不是同一個類型。比如

struct A:B{B b;int c; } //不符合這個條件。因為A中第一個成員是基類B類型的

(4).沒有虛類和虛基類(與trival中重復)

(5).所有非靜態數據成員都符合標準布局的要求,這其實就是一個遞歸的定義。

C++11中,我們使用模版類std::is_standard_layout<A>::value來判斷類型是否是一個標準布局類型。

?

所以在C++11中,POD就是滿足平凡的(trival)和標準布局(standard layout)這兩個方面。 可以使用<type_traits>中的is_pod<T>::value判斷T是不是POD類型的。 #include <iostream>using namespace std;class A { private:int a; public:int b; };class B1 {static int x1; };class B2 {int x2; };class B : B1, B2 {int x; };class C1 {}; class C : C1 {C1 c; };class D { virtual void foo() = 0; }; class E : D {}; class F { A x; };int main() {std::cout << std::is_standard_layout<A>::value << std::endl; //違反定義1,成員a和b具有不同的訪問權限std::cout << std::is_standard_layout<B>::value << std::endl; //違反定義2,繼承樹有兩個(含)以上的類有非靜態成員std::cout << std::is_standard_layout<C>::value << std::endl; //違反定義3,第一個非靜態成員是基類類型std::cout << std::is_standard_layout<D>::value << std::endl; //違反定義4,有虛函數std::cout << std::is_standard_layout<E>::value << std::endl; //違反定義5,有虛基類std::cout << std::is_standard_layout<F>::value << std::endl; //違反定義6,非靜態成員x不符合標準布局類型return 0; } View Code #include <iostream> #include <cstring>using namespace std;class AA { public:int x;double y; };int main() {if (std::is_pod<AA>::value) {cout << "before" << endl;AA aa;aa.x = 10;aa.y = 20.0f;cout << aa.x << " " << aa.y << endl;size_t size = sizeof(aa);char *p = new char[size];memcpy(p, &aa, size);AA *pA = (AA*)p;cout << "after" << endl;cout << pA->x << " " << pA->y << endl;delete p;}return 0; } View Code

?

說了這么多,那么為什么我們需要POD這種條件滿足的數據呢?

  (1).可以使用字節賦值,比如memset,memcpy操作

  (2).對C內存布局兼容。

  (3).保證了靜態初始化的安全有效。

總結

以上是生活随笔為你收集整理的C++11 POD类型的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。