跟我学C++中级篇——POD数据类型及演进

215 篇文章 28 订阅

一、POD数据类型

首先说明,所谓POD类型不是常说的标准中的int,double这种数据类型。它是一种与C语言兼容的类型,能够直接以二进制形式与C库进行交互。这样说可能不好理解,意思就是说它可以直接使用memcpy,memmove等函数进行赋值。 POD(Plain Old Data,简旧数据)类型,是一种C++与C标准兼容的数据类型统称。用官话说:“This is a type category defined by the core language. It is included here as a named requirement only for consistency.”
在C++11以后,C++又定义了几种此种类型的类型,即平凡类型 (TrivialType) ,标量类型 (ScalarType) 和标准布局类型 (StandardLayoutType) 。所以需要注意的是,在新的C++20标准中,此种数据类型已经不再使用,即不再使用POD称呼这种类型,而不是说这种类型的数据真的不存在了。
那么什么样的数据类型可以被认为是POD数据类型呢:
1、标量类型
2、POD 类
3、上述类型的数组
4、这些类型的有 cv 限定版本
POD类的定义:
C++11标准前:
1、它是聚合体
2、没有用户声明的复制赋值运算符
3、没有用户声明的析构函数,并且没有具有非 POD 类类型(或这种类型的数组)或者引用类型的非静态数据成员。
C++11标准后:
4、它不但是平凡类,还是标准布局类(trivial and stdlayout),并且没有具有非 POD 类类型(或这种类型的数组)的非静态数据成员。
POD 结构体 是非联合体的 POD 类。POD 联合体 是满足 POD 类条件的联合体。
再看一下什么是聚合体:
1、数组类型
2、符合以下条件的类类型:
没有用户声明的构造函数 (C++11 前)
没有用户提供、继承或 explicit 的构造函数 (C++11 ~C++20)
没有用户声明或继承的构造函数 (C++20 起)
没有私有或受保护的直接 非静态数据成员 (C++17 起)
没有基类 (C++17 前)
没有虚基类(C++17 起)
没有私有或受保护的直接基类 (C++17 起)
没有虚成员函数
没有默认成员初始化器 (C++11~C++14 )

这样就可以得出POD数据类型的特点是:它是平坦且连续的内存,可以嵌套但非静态成员变量必须也是POD类型(污染扩展),可以放心的使用C库中的函数进行操作。静态成员属于类作用域,不是对象的属性,所以其不影响一个类或结构体是否为POD类型。

二、平凡类型 (TrivialType)

在前文“c++中的trivial”对平凡类型进行了基础的介绍和分析,这里再简要说明一遍。平凡类型包括:“ 标量类型,平凡类类型,上述类型的数组,这些类型的有 cv限定版本”。这里重点介绍一下平凡类。它是满足以下所有条件的类:它是可平凡复制类,并且有一个或多个合格的默认构造函数,它们全部都是平凡的。 而平凡复制类就是指符合下面的条件的类:
1、至少有一个合格的复制构造函数,移动构造函数,复制赋值运算符或移动赋值运算符
2、每个合格的复制构造函数都是平凡的
3、每个合格的移动构造函数都是平凡的
4、每个合格的复制赋值运算符都是平凡的
5、每个合格的移动赋值运算符都是平凡的,并且有一个未被弃置的平凡析构函数
而所谓平凡是指:
1、它不是用户提供的(即它是隐式定义或预置的)
2、类型T 没有虚成员函数
3、类型T 没有虚基类
4、为 T 的每个直接基类选择的移动构造函数都是平凡的
5、为 T 的每个类类型(或类类型数组)的非静态成员选择的移动构造函数都是平凡的
说白了就是可以兼容C库中的memset,memmove等操作的,连续内存空间地址的类型。或说用一句不太准确的大白话来说,在C++中类默认有六个函数(默认构造、析构、赋值、拷贝、移动拷贝、移动赋值),它们都是使用默认而非用户显示定义的。即这六个函数只是一个符合标准的架子,不参与额外的动作。

三、标量类型 (ScalarType)

这个类型最好理解,其实就是标准里定义的基础数据类型即:
1、算术类型
2、枚举类型
3、指针类型
4、成员指针类型
5、std::nullptr_t (C++11 起)
6、这些类型的有 cv 限定版本

四、标准布局类型 (StandardLayoutType)

这就需要明白什么是标准布局:
当且仅当类是 POD 类时它被当成是标准布局 的。POD类刚刚已经介绍了。
它有以下几种:
1、标量类型
2、标准布局类类型
3、上述类型的数组
4、这些类型的有 cv 限定版本
简单介绍一下标准布局类类型:
1、没有具有非标准布局类类型(或这种类型的数组)或引用类型的非静态数据成员
2、没有虚函数和虚基类
3、所有非静态数据成员都具有相同的可访问性
4、没有非标准布局的基类
5、继承层级中仅有一个类具有非静态数据成员,并且简单的限定,该类的所有基类的类型均不同于第一个非静态数据成员,准确的限定见标准文档
标准布局意味着可以和不同的语言之间进行互操作。这个非常好理解,原来写动态库的接口导出时,在Windows平台上就有各种定义接口导出方式,这个本质是相同的。再结合平凡的类型是连续递增的地址空间,而POD类型是这两个的共同要求,这样就可以明白,为什么C语言的数据结构体可以在不同的语言和平台上进行交互的原因了吧。

五 、总结

现在都知道数据是资产了,数据的定义就有数据类型,可以看这几种类型当成一种更抽象的层次的数据类型。怎么理解这句话呢?可以把常见的各种语言中的数据类型定义(如int,float等 )当成普通数据类型,而上面分析的数据类型理解为这些数据类型以上的更高层次的抽象。只要满足了特定的要求,就可以将其理解为这种数据类型。绕来绕去,真麻烦。
这些数据类型有什么 用处呢?其实是兼容扩展,能够和其它语言保持数据交互,这其实是相当重要的。沟通几乎能治百病,慢慢理解。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值