POD是Plain Old Data的缩写。POD类型是C++11中其他概念的基础,在后续会看到各处的应用。
Plain指的是每个类都有这样的属性,Old指的是与C的兼容,比如用memcpy()、memset()进行赋值。
C++11将POD划分成两个基本概念的合集:平凡的(trivial)和标准布局的(standard layout)。
两个条件是缺一不可的。
trivial
一个平凡的类或结构体应当符合以下条件:
- 拥有平凡的默认构造函数和默认析构函数
当自定义了构造/析构函数时,默认函数会被删掉,哪怕自定义的构造/析构函数啥也没干,也会不符合trivial。
有个技巧是可以通过=default关键帧恢复trivial。 - 拥有平凡的拷贝构造函数和移动构造函数
- 拥有平凡的拷贝赋值运算符和移动赋值运算符
- 不能包含虚函数以及虚基类
我们看几个示例。
#include <iostream>
#include <type_traits>
using namespace std;
struct Trivial1 {};
struct Trivial2 {
public:
int a;
private:
int b; // 同时有public和private符合trivial,但不符合standard layout
};
struct Trivial3 {
Trivial1 a;
Trivial2 b;
};
struct Trivial4 {
Trivial2 a[23];
};
struct Trivial5 {
int x;
static int y; // 同时也是standard layout和pod
};
struct NonTrivial1 {
NonTrivial1(): z(42) {}
int z;
};
struct NonTrivial2 {
NonTrivial2();
int w;
};
NonTrivial2::NonTrivial2() = default; // 实测这样写无法恢复,但写在里面是可以的
struct NonTrivial3 {
Trivial5 c;
virtual void f();
};
int main() {
cout << is_trivial<Trivial1>::value << endl;
cout << is_trivial<Trivial2>::value << endl;
cout << is_standard_layout<Trivial2>::value << endl; // 0
cout << is_pod<Trivial2>::value << endl; // 0
cout << is_trivial<Trivial3>::value << endl;
cout << is_trivial<Trivial4>::value << endl;
cout << is_trivial<Trivial5>::value << endl;
cout << is_standard_layout<Trivial5>::value << endl; // 1
cout << is_pod<Trivial5>::value << endl; // 1
cout << is_trivial<NonTrivial1>::value << endl;
cout << is_trivial<NonTrivial2>::value << endl;
cout << is_trivial<NonTrivial3>::value << endl;
}
网友评论