POD
(plain old data
)介绍
简旧类型(plain old data
)
- 一个标量类型(
scalar type
) - 简旧类型(POD)数组
- 一个符合以下要求的
class
类型(class
orstruct
orunion
)- C++11以前:
- 是一个聚合类型(
aggregate type
) - 所有非静态成员都是简旧类型(
POD
) - 没有成员是引用类型
- 没有用户定义的拷贝构造函数
- 没有用户定义的析构函数
- 是一个聚合类型(
- C++11以后
- 是一个平凡类型(
trivial type
) - 是一个标准布局类型
- 所有非静态成员是简旧类型(
POD
)
- 是一个平凡类型(
- C++11以前:
POD类型特别在哪里?
What are Aggregates and PODs and how/why are they special?
像POD-classes
,PD-unions
, scalar type
和数组
这样的类型被统一的叫做POD-types
, PODs
在很多地方都非常特别。下面一些例子。
POD-classes
最接近C语言形式的结构体。不同的是,PODs
可以有成员函数和任意静态成员,但他们两者都不能改变对象的内存排布。所以假如你想要写一个或多或少可移植型的可以被C语言甚至.NET
使用的动态库,你应该尝试你所有导出的函数和返回值都是POD-types
.- 一个
non-POD
类类型对象的生存周期开始于当构造函数结束,结束于当析构函数结束。对于POD
类型类,生命周期开始于内存空间被对象占用,结束于内存空间被释放或者被重用后。 - 对于
POD
类型的对象, 标准保证它当你使用memcpy
对你对象中内容转化为char
或unsigned
数组时,然后memcpy
这个内容回到你的对象内,这个对象将持有原始的值。请注意:对于non-POD
类型对象没有这样的保证。下面的例子假设类型T
是POD
类型。
1 |
|
goto
语句. 你可能知道,通过goto从一个一些变量还没有在这个作用域中定义的点跳转到一个已经定义的点是非法的(编译器会报错)。这个限制应用在只有当这个变量是一个non-POD
类型。看下面例子中f()
是语义错误,g()
则符合语义。注意,微软编译器在这条规则上特别松散,它在这两个情况下只是抛出一个警告。
1 | int f() |
- 它保证了在
POD
对象的开始处没有内存填充位。其他情况下,假如一个POD-class: A
使一个类型T
的第一个成员,你可以安全的使用reinterpret_cast
从A*
到T*
然后获取指向第一个成员的指针,反之亦然。
补充定义
标量类型(scalar type
)
scalar type
是一个不是数组类型或class
类型的(可能const
或volatile
限定的[^2])object
类型.
英文原文[^1]
scalar types are (possibly cv-qualified) object types that are not array types or class types
聚合类型(aggregate type
)
首先介绍一下聚合类型
:
聚合类型是以下类型的其中一种[^3]:
- 数组类型
class
类型(典型的例子,struct
,union
):- 没有
private
和protected
非静态数据成员(到C++11) - 没有用户定义的构造函数(显式的默认或删除的构造函数) (C++11起, 到C++17)
- 没有用户提供的继承的或显式的构造函数(显式的默认或删除的构造函数)(C++17起,到C++20)
- 没有用户定义的或继承的构造函数(C++20起)
- 没有基类(C++17之前), 没有
virtual
,private
,protected
基类(C++17起) - 没有虚成员函数
- 没有默认成员的初始化器(从C++11到C++14)
- 没有
平凡类型 (TrivialType
)
要求[^4]:
- 可平凡复制(
TrivialCopyable
) - 若该类型是类类型或其数组,则该类拥有一个或多个合格的默认构造函数,均为平凡的
可平凡可复制(Trivially Copyable
)
下面列举的类型称作平凡可复制类型[^5]:
- 标量类型
- 平凡可复制的类
- 至少有一个拷贝构造函数,移动构造函数,拷贝赋值符是符合要求的
- 每个合格的拷贝构造函数(假如有的话)是平凡的
- 每个合格的移动构造函数(假如有的话)是平凡的
- 每个合格的拷贝赋值符(假如有的话)是平凡的
- 每个合格的移动赋值符(假如有的话)是平凡的
- 有一个平凡的没有被删除的析构函数
- 可平凡复制的数组类型
这意味着一个平凡可拷贝的class
没有虚函数和虚基类函数。
参考文献和扩展阅读
[^1]:What is a scalar Object in C++?
[^2]:What does “cv-unqualified” mean in C++?, cv (const and volatile) type qualifiers
[^3]:C++ standard: aggregate type
[^4]:C++ standard: C++ named requirements: TrivialType
[^5]: C++ standard: C++ named requirements: TriviallyCopyable