0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
电子发烧友
开通电子发烧友VIP会员 尊享10大特权
海量资料免费下载
精品直播免费看
优质内容免费畅学
课程9折专享价
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

POD到底是什么?聊聊POD

CPP開發(fā)者 ? 來源:高性能架構(gòu)探索 ? 2023-06-19 15:24 ? 次閱讀

概述

POD,即Plain Old Data的縮寫,plain代表普通,Old代表舊,從字面意思看是老的、普通的數(shù)據(jù)類型。這個(gè)概念由C++引入主要是為了與C兼容,或者說POD就是與C兼容的那邊部分?jǐn)?shù)據(jù)類型。在C++對(duì)POD類型進(jìn)行序列化生成二進(jìn)制后,在C語言中可以對(duì)該二進(jìn)制進(jìn)行解析成功。如果對(duì)于一個(gè)非POD類型,假如包含虛函數(shù)的class,大家知道編譯器在操作的時(shí)候會(huì)加入虛函數(shù)指針,但是虛函數(shù)這個(gè)概念在C語言中不存在,遇到這種數(shù)據(jù)編譯器就不認(rèn)識(shí)了,或者說對(duì)于一個(gè)非POD類型的數(shù)據(jù),C語言是不識(shí)別的,于是C++就提出了POD數(shù)據(jù)類型的概念。

POD的一種常見用法是跨系統(tǒng)或者跨語言進(jìn)行通訊,比如與C/.NET等編寫的代碼進(jìn)行通訊。

概念

structA{
intx;
inty;
};
structB{
private:
intx;
public:
inty;
};
structC{
inta;
intb;
C(intx,inty):a{x},b{y}{}
};

那么,問題來了,上述三個(gè)類型A、B和C,哪個(gè)是POD類型?

如果我們不清楚POD的判斷標(biāo)準(zhǔn)的話,只能靠猜來回答該問題,幸運(yùn)的是Modern Cpp提供了接口來進(jìn)行判斷(PS:下面的trivial和standard layout用來輔助判斷):

C++11 C++17 描述
std::is_pod std::is_pod_v 通過其value是否為ture來表示是否為POD類型(std::is_pod::value)
std::is_trivial std::is_trivial_v 通過其value是否為ture來表示是否為平凡類型(std::is_trivial::value)
std::is_standard_layout std::is_standard_layout_v 通過其value是否為ture來表示是否為標(biāo)準(zhǔn)布局(std::is_standard_layout::value)

如果使用上述接口對(duì)前面例子中的對(duì)象A、B和C進(jìn)行判斷的話,結(jié)果如下:

類型 Trivial(平凡類型) Standard layout(標(biāo)準(zhǔn)布局) POD
A
B
C

從上述結(jié)果可以看出,B是平凡類型,C是標(biāo)準(zhǔn)布局,A既是平凡類型,又是標(biāo)準(zhǔn)布局,同時(shí)也是POD類型,這就引出了POD的定義:

A POD type is a type that is both trivial and standard-layout. This definition must hold recursively for all its non-static data members.

通過上述定義可以看出,POD類型既是平凡類型又是標(biāo)準(zhǔn)布局,反過來可以理解為如果一個(gè)類型既是平凡類型又是標(biāo)準(zhǔn)布局,且其內(nèi)部非靜態(tài)成員變量也滿足該條件(既是平凡類型又是標(biāo)準(zhǔn)布局),那么這個(gè)類型就是POD類型。

標(biāo)準(zhǔn)對(duì)POD定義如下:

A POD class is a class that is both a trivial class and a standard-layout class, and has no non-static data members of type non-POD class (or array thereof). A POD type is a scalar type, a POD class, an array of such a type, or a cv-qualified version of one of these types.

與前一個(gè)定義相比,新增了一個(gè)類型scalar type,cppference中提到,scalar type為以下幾個(gè)之一:

?an arithmetic type

?an enumeration type

?a pointer type

?a pointer-to-member type

?thestd::nullptr_ttype

?cv-qualified versions of the above types

好了,從上面的內(nèi)容中提到,一個(gè)POD類型的類,其非靜態(tài)成員變量也必須是POD的,對(duì)靜態(tài)成員變量和成員函數(shù)則沒有這個(gè)要求,如下這個(gè)類D,其仍然是POD:

structD{
inta;
intb;
staticstd::strings;
intget(){
returna;
}
};

在本小節(jié)中,我們提到了三個(gè)概念:Trivial(平凡類型)、Standard layout(標(biāo)準(zhǔn)布局)以及Scalar type,對(duì)于最后一個(gè)Scalar type比較簡單,所以在后面的內(nèi)容中,將針對(duì)前兩個(gè)概念進(jìn)行詳細(xì)分析。

Trivial

這個(gè)概念比較抽象,乃至于很難用一句簡單的話來描述。于是查閱了cppreference,顯示標(biāo)準(zhǔn)對(duì)這塊也沒有一個(gè)完整的定義:

Note: the standard doesn't define a named requirement with this name. This is a type category defined by the core language. It is included here as a named requirement only for consistency.

于是搜索了相關(guān)資料,微軟官網(wǎng)對(duì)這塊的定義如下:

When a class or struct in C++ has compiler-provided or explicitly defaulted special member functions, then it is a trivial type. It occupies a contiguous memory area. It can have members with different access specifiers. In C++, the compiler is free to choose how to order members in this situation.

也就是說,當(dāng)一個(gè)類型(class/struct)同時(shí)滿足以下幾個(gè)條件時(shí),它就是trivial type:

?沒有虛函數(shù)或虛基類。

?由編譯器生成(使用=default或者=delete)默認(rèn)的特殊成員函數(shù),包括默認(rèn)構(gòu)造函數(shù)、拷貝構(gòu)造函數(shù)、移動(dòng)構(gòu)造函數(shù)、賦值運(yùn)算符、移動(dòng)賦值運(yùn)算符和析構(gòu)函數(shù)。

?數(shù)據(jù)成員同樣需要滿足條件 1 和 2。

舉例如下:

classA{
public:
A(inti):n(i){}
A(){}
private:
intn;
};

classB{
public:
B(inti):n(i){}
B()=default;
private:
intn;
};

classC{
public:
C(inti):n(i){}
C()=delete;
private:
intn;
};

structBase{
intx;
inty;
};

structDerived:publicBase
{
private:
intz;
};

intmain(){
std::cout<::value<::value<::value<::value<::value<

平凡類型具有如下屬性:

?占據(jù)一塊連續(xù)的內(nèi)存區(qū)域

?由于對(duì)齊要求,成員變量之間可以填充對(duì)齊字節(jié)(padding)

?可以使用 memcpy進(jìn)行對(duì)象拷貝

?可以將一個(gè)平凡的類型通過memcpy()放入char或者unsigned char數(shù)組,然后可以把數(shù)組內(nèi)的內(nèi)容重新組裝成一個(gè)該類型對(duì)象

?允許有多個(gè)不同的訪問控制符,但是,在這種情況下,編譯器有可能對(duì)其進(jìn)行重排

針對(duì)上述最后一個(gè)屬性,示例如下:

structC{
public:
intx;

private:
inty;

public:
intz;
};

編譯器可以將其重新排序?yàn)槿缦逻@種:

structC{
public:
intx;
intz;
private:
inty;
};

正是因?yàn)槿缟显?訪問權(quán)限編譯器重排),普通類型不能安全的與其他語言編寫的代碼進(jìn)行交互操作。我們以C語言為例,編譯器的重排導(dǎo)致不能不能與C語言兼容(或者說C語言解析失敗),因?yàn)镃語言不識(shí)別private這個(gè)訪問權(quán)限,如果進(jìn)行交互操作,可能會(huì)導(dǎo)致其他意想不到的問題。

Standard layout

布局指的是類、結(jié)構(gòu)體或者聯(lián)合(Union)的成員在內(nèi)存中的排列。標(biāo)準(zhǔn)布局定義了這樣一種類型,它不使用C中不存在的而在CPP中存在的某些功能或者特性。如果某個(gè)類是標(biāo)準(zhǔn)布局,那么可以通過memcpy進(jìn)行復(fù)制,而且可以與C語言中定義的同種類型進(jìn)行交互。一言以蔽之,具有標(biāo)準(zhǔn)布局類的類或者結(jié)構(gòu)體等與C兼容,并行可以通過C的API進(jìn)行交互。

既然符合標(biāo)準(zhǔn)布局的類只具有C語言中存在的功能或者特性,那么,很容易總結(jié)出來標(biāo)準(zhǔn)布局的條件:

1.沒有虛函數(shù)或者虛基類

2.沒有引用類型的非靜態(tài)成員變量

3.所有的非靜態(tài)成員變量具有相同的訪問控制權(quán)限

4.所有的非靜態(tài)成員變量和基類都是標(biāo)準(zhǔn)布局

5.沒有多重繼承導(dǎo)致的菱形問題

6.子類中的第一個(gè)非靜態(tài)成員的類型與其基類不同

7.在class或者struct繼承時(shí),滿足以下兩種情況之一(總結(jié)就是要么子類有非靜態(tài)成員變量,要么父類有):

?派生類中有非靜態(tài)成員,且只有一個(gè)僅包含靜態(tài)成員的基類

?基類有非靜態(tài)成員,而派生類沒有非靜態(tài)成員

現(xiàn)在我們結(jié)合示例代碼進(jìn)行分析:

structA{
};
structB{
Aa;
doubleb;
};
structC{
voidfoo(){}
};
structD:publicC
{
intx;
inty;
};

依據(jù)前面標(biāo)準(zhǔn)布局的要求,上述幾個(gè)類A、B、C和D都是標(biāo)準(zhǔn)布局?,F(xiàn)在我們構(gòu)造稍微復(fù)雜點(diǎn)的例子:

structE
{
intx;
};

structF:publicE
{
inty;
};

structG
{
intx;
private:
virtualvoidfoo(){};
};

structH{};
structX:publicH{};
structY:publicH{};
structK:publicX,Y{};

structL{
intx;
private:
inty;
};

上面這些例子中,E是標(biāo)準(zhǔn)布局,G不屬于標(biāo)準(zhǔn)布局(虛函數(shù),不滿足條件1),K不屬于標(biāo)準(zhǔn)布局(菱形繼承,不滿足條件5),L不屬于標(biāo)準(zhǔn)布局(不同的訪問權(quán)限,不滿足條件3)

接著我們看下前面條件中比較難理解的一個(gè)子類中的第一個(gè)非靜態(tài)成員的類型與其基類不同,示例如下:

structM{
intx;
};

structN:publicM{
Mm;
inta;
};

structX{
intx;
};

structY:publicX{

};

structZ:publicX{
inty;
};

在上述例子中,M、X和Y是標(biāo)準(zhǔn)布局,而N(不滿足條件6)和Z(不滿足條件7)不是標(biāo)準(zhǔn)類型。


審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1657

    瀏覽量

    49960
  • C++語言
    +關(guān)注

    關(guān)注

    0

    文章

    147

    瀏覽量

    7246
  • POD
    POD
    +關(guān)注

    關(guān)注

    0

    文章

    18

    瀏覽量

    6131

原文標(biāo)題:我們通常說的 POD 到底是什么?

文章出處:【微信號(hào):CPP開發(fā)者,微信公眾號(hào):CPP開發(fā)者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 0人收藏

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    介紹如何安裝E1135C PDU和Pod升級(jí)

    Describes how to install the E1135C PDU and Pod upgrade.
    發(fā)表于 08-21 14:07

    從零開始入門 K8s| 詳解 Pod 及容器設(shè)計(jì)模式

    LogCollector 容器給看到。以上就是 Pod 實(shí)現(xiàn)存儲(chǔ)的方式。三、詳解容器設(shè)計(jì)模式現(xiàn)在我們知道了為什么需要 Pod,也了解了 Pod 這個(gè)東西到底是怎么實(shí)現(xiàn)的。最后,以此為
    發(fā)表于 09-20 15:12

    Pod資源配置

    《Kubernetes進(jìn)階實(shí)戰(zhàn)》第四章《管理Pod資源對(duì)象》
    發(fā)表于 10-22 14:39

    Land Pattern and POD

    Land Pattern and POD
    發(fā)表于 03-05 15:59 ?0次下載
    Land Pattern and <b class='flag-5'>POD</b>

    Kubernetes組件pod核心原理

    1. 核心組件原理 —— pod 核心原理 1.1 pod 是什么 pod 也可以理解是一個(gè)容器,裝的是 docker 創(chuàng)建的容器,也就是用來封裝容器的一個(gè)容器; pod 是一個(gè)虛擬化
    的頭像 發(fā)表于 09-02 09:27 ?2050次閱讀

    pod底層網(wǎng)絡(luò)和數(shù)據(jù)存儲(chǔ)是如何進(jìn)行的

    1. 核心組件原理 —— pod 核心原理 1.1 pod 是什么 pod 也可以理解是一個(gè)容器,裝的是 docker 創(chuàng)建的容器,也就是用來封裝容器的一個(gè)容器; pod 是一個(gè)虛擬化
    的頭像 發(fā)表于 09-24 11:35 ?1892次閱讀

    如何利用Docker實(shí)現(xiàn)Pod

    Container 和 Pod 是相似的。在底層,它們主要依賴 Linux 命名空間和 cgroup。但是,Pod 不僅僅是一組容器。Pod 是一個(gè)自給自足的高級(jí)構(gòu)造。
    發(fā)表于 11-14 12:51 ?1550次閱讀

    Kubernetes中的Pod簡易理解

    Pod是Kubernetes中非常重要的概念,也是Kubernetes管理的基本單位。正如其名,Pod像一個(gè)豌豆莢,可以容納多個(gè)container,擁有相同的IP地址。
    的頭像 發(fā)表于 02-15 10:44 ?1486次閱讀

    什么是CNI,基于Calico的Pod網(wǎng)絡(luò)介紹

    每一個(gè)Node上都會(huì)有一個(gè)tunl0的虛擬網(wǎng)卡,這個(gè)網(wǎng)卡可以理解成網(wǎng)橋,所有Pod都要基于此網(wǎng)橋來和其它Pod通信。 ② 每生成一個(gè)新的Pod,那么在Node上都會(huì)生成一個(gè)calixxxx的虛擬網(wǎng)卡,這個(gè)網(wǎng)卡會(huì)對(duì)應(yīng)到
    發(fā)表于 04-20 09:37 ?2731次閱讀

    k8s與pod之間是如何進(jìn)行網(wǎng)絡(luò)隔離的?

    NetworkPolicy用來控制PodPod之間的網(wǎng)絡(luò)通信,它也支持針對(duì)Namespace進(jìn)行限制。
    的頭像 發(fā)表于 05-11 09:35 ?1866次閱讀
    k8s與<b class='flag-5'>pod</b>之間是如何進(jìn)行網(wǎng)絡(luò)隔離的?

    iOS中Pod庫資源引用探究

    Cocoapods中Pod引用資源的方式有多種,不同的方式對(duì)資源的使用還是有區(qū)別的,但也有一定的規(guī)律,這里我用一個(gè)樣例工程來進(jìn)行說明,樣例工程名叫:AssetsDemo,使用pod lib create AssetsDemo命令創(chuàng)建,目錄結(jié)構(gòu)如圖:
    的頭像 發(fā)表于 05-26 11:11 ?1112次閱讀
    iOS中<b class='flag-5'>Pod</b>庫資源引用探究

    Pod是如何在底層實(shí)現(xiàn)的?如何使用Docker創(chuàng)建Pod?

    剛開始接觸 Kubernetes 時(shí),你學(xué)到的第一件事就是每個(gè) Pod 都有一個(gè)唯一的 IP 和主機(jī)名,并且在同一個(gè) Pod 中,容器可以通過 localhost 相互通信。所以,顯而易見,一個(gè) Pod 就像一個(gè)微型的服務(wù)器。
    的頭像 發(fā)表于 08-14 10:33 ?1560次閱讀
    <b class='flag-5'>Pod</b>是如何在底層實(shí)現(xiàn)的?如何使用Docker創(chuàng)建<b class='flag-5'>Pod</b>?

    Pod一直處于Pending狀態(tài)?什么是Pod拓?fù)浼s束?

    起因: 今天在部署組件的時(shí)候,發(fā)現(xiàn)組件的pod一直處于Pending狀態(tài),報(bào)錯(cuò)顯示的原因是:不滿足Pod拓?fù)浞植技s束,看了代碼發(fā)現(xiàn)是原來同事給組件新增了Pod拓?fù)浼s束。
    的頭像 發(fā)表于 12-18 11:46 ?1555次閱讀
    <b class='flag-5'>Pod</b>一直處于Pending狀態(tài)?什么是<b class='flag-5'>Pod</b>拓?fù)浼s束?

    Kubernetes Pod常用管理命令詳解

    Kubernetes Pod常用管理命令詳解
    的頭像 發(fā)表于 02-17 14:06 ?440次閱讀
    Kubernetes <b class='flag-5'>Pod</b>常用管理命令詳解

    詳解Kubernetes中的Pod調(diào)度親和性

    在 Kubernetes(K8s)中,Pod 調(diào)度親和性(Affinity) 是一種高級(jí)調(diào)度策略,用于控制 Pod 與節(jié)點(diǎn)(Node)或其他 Pod 之間的關(guān)聯(lián)(親和)或反關(guān)聯(lián)(反親和)關(guān)系。通過親和性規(guī)則,管理員可以更精細(xì)地控
    的頭像 發(fā)表于 06-07 13:56 ?115次閱讀

    電子發(fā)燒友

    中國電子工程師最喜歡的網(wǎng)站

    • 2931785位工程師會(huì)員交流學(xué)習(xí)
    • 獲取您個(gè)性化的科技前沿技術(shù)信息
    • 參加活動(dòng)獲取豐厚的禮品