概述
POD(Plain old data), 平凡的数据, 也是旧 C 语言中的那些类型。 POD 类型还包括标量类型。 POD 类类型是既平凡(可以静态初始化)trivial和标准布局Standard layout(这是一个简单的数据结构,如结构和联合)的类类型。
std::is_pod的原型:template
模板只能有类型 T 的参数,并检查给定的类型是否为普通旧数据类型,它返回一个布尔值,如果给定类型是普通旧数据,则返回 true,如果给定类型不是普通旧数据,则返回 false。
C++基础回顾
1、 C++定义一个类 class CTest{}; 系统编译器会默认生成的函数有:
1)默认构造函数,没有参数, 如: CTest() = default;
2)拷贝构造函数, 如:CTest(const CTest& test) = default;
3)拷贝赋值操作符, 如:CTest& operator=(const CTest& test) =default;
4) 默认析构函数, 如:~CTest() =default;
5)移动构造函数, 如: CTest(const CTest&& test) = default;
6)移动赋值操作符,如:CTest& operator=(CTest&& test) =default;
2、当自定义类型时,如果编码实现了任意一个构造函数,则编译器将不会自动合成默认构造函数。C++11中可使用=default显示声明默认构造函数,加了关键字=default生成的构造函数和默认构造函数是一个效果
3、当自定义类型时,如果需要限制类的某些构造函数调用,在C++11中可使用=delete来阻止用户的调用
Trivial 类型
极简 (trivial),可以通过std::is_trivial
判断,判断trivial的条件是:
- 有平凡的构造函数
- 有平凡的拷贝构造函数
- 有平凡的移动构造函数
- 有平凡的拷贝赋值运算符
- 有平凡的移动赋值运算符
- 有平凡的析构函数
- 不能包含虚函数
- 不能包含虚基类
- 成员变量及基类也要满足上述条件
判断下面定义的几个struct是否是trivial类型:
- class MyTest1{
- int m1;
- };
-
- class MyTest2{
- public:
- MyTest2(double val):m1(val){}
- private:
- double m1;
- };
-
- class MyTest3{
- public:
- MyTest2(int val = 0):n(val){}
- private:
- int n;
- };
-
- class MyTest4{
- public:
- MyTest4(){}
- MyTest4(int val):n(val){}
- private:
- int n;
- };
-
- class MyTest5{
- public:
- MyTest5() = default;
- MyTest5(int val):n(val){}
- private:
- int n;
- };
-
- class MyTest6{
- public:
- MyTest6() = default;
- MyTest6(MyTest6&& val);
- private:
- MyTest6* m_pTest;
- };
-
- printf("is_trivial
:%d\n" , std::is_trivial::value);// true - printf("is_trivial
:%d\n" , std::is_trivial::value);// false - printf("is_trivial
:%d\n" , std::is_trivial::value);// false - printf("is_trivial
:%d\n" , std::is_trivial::value);// false - printf("is_trivial
:%d\n" , std::is_trivial::value);// true - printf("is_trivial
:%d\n" , std::is_trivial::value);// false
标准布局 (standard layout)
标准布局 (standard layout),可以通过std::is_standard_layout
判断,满足标准布局的条件有:
- 所有非静态成员有相同的访问权限
- 继承树中最多只能有一个类有非静态数据成员
- 子类的第一个非静态成员不可以是基类类型
- 没有虚函数
- 没有虚基类
- 所有非静态成员都符合标准布局类型
- struct S1{
- int i;
- };
-
- struct B1{
- void foo(){}
- };
- struct S2 : public B1{
- int i;
- };
-
- struct B2{
- int n;
- };
- struct S3 : public B2{};
-
- struct S4 : public B2{
- int i;
- };
-
- struct S5 : public B1{
- B1 b;
- int m;
- };
-
- struct S6 : public B1{
- int m;
- B1 b;
- };
-
- struct S7 : virtual public B1{};
-
- struct S8{
- S8(int val):mVal(val){}
- private :
- int mVal;
- };
-
- // Trivial but not standard-layout
- struct S9{
- public:
- int m;
- private:
- int n;
- };
-
- printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// true - printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// true - printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// true - printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// false - printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// false - printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// true - printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// false - printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// true - printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// false -
- printf("\n\n");
- printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// true - printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// true
总结
POD 类 是满足以下所有条件的类:
| (C++11 前) |
| (C++11 起) |
POD 结构体 是非联合体的 POD 类。POD 联合体 是满足 POD 类条件的联合体。
POD 属性的使用被弃用。用户代码应该期待或要求平凡或标准布局属性,或者它们两者。 | (C++20 起) |
概述
POD(Plain old data), 平凡的数据, 也是旧 C 语言中的那些类型。 POD 类型还包括标量类型。 POD 类类型是既平凡(可以静态初始化)trivial和标准布局Standard layout(这是一个简单的数据结构,如结构和联合)的类类型。
std::is_pod的原型:template
模板只能有类型 T 的参数,并检查给定的类型是否为普通旧数据类型,它返回一个布尔值,如果给定类型是普通旧数据,则返回 true,如果给定类型不是普通旧数据,则返回 false。
C++基础回顾
1、 C++定义一个类 class CTest{}; 系统编译器会默认生成的函数有:
1)默认构造函数,没有参数, 如: CTest() = default;
2)拷贝构造函数, 如:CTest(const CTest& test) = default;
3)拷贝赋值操作符, 如:CTest& operator=(const CTest& test) =default;
4) 默认析构函数, 如:~CTest() =default;
5)移动构造函数, 如: CTest(const CTest&& test) = default;
6)移动赋值操作符,如:CTest& operator=(CTest&& test) =default;
2、当自定义类型时,如果编码实现了任意一个构造函数,则编译器将不会自动合成默认构造函数。C++11中可使用=default显示声明默认构造函数,加了关键字=default生成的构造函数和默认构造函数是一个效果
3、当自定义类型时,如果需要限制类的某些构造函数调用,在C++11中可使用=delete来阻止用户的调用
Trivial 类型
极简 (trivial),可以通过std::is_trivial
判断,判断trivial的条件是:
- 有平凡的构造函数
- 有平凡的拷贝构造函数
- 有平凡的移动构造函数
- 有平凡的拷贝赋值运算符
- 有平凡的移动赋值运算符
- 有平凡的析构函数
- 不能包含虚函数
- 不能包含虚基类
- 成员变量及基类也要满足上述条件
判断下面定义的几个struct是否是trivial类型:
- class MyTest1{
- int m1;
- };
-
- class MyTest2{
- public:
- MyTest2(double val):m1(val){}
- private:
- double m1;
- };
-
- class MyTest3{
- public:
- MyTest2(int val = 0):n(val){}
- private:
- int n;
- };
-
- class MyTest4{
- public:
- MyTest4(){}
- MyTest4(int val):n(val){}
- private:
- int n;
- };
-
- class MyTest5{
- public:
- MyTest5() = default;
- MyTest5(int val):n(val){}
- private:
- int n;
- };
-
- class MyTest6{
- public:
- MyTest6() = default;
- MyTest6(MyTest6&& val);
- private:
- MyTest6* m_pTest;
- };
-
- printf("is_trivial
:%d\n" , std::is_trivial::value);// true - printf("is_trivial
:%d\n" , std::is_trivial::value);// false - printf("is_trivial
:%d\n" , std::is_trivial::value);// false - printf("is_trivial
:%d\n" , std::is_trivial::value);// false - printf("is_trivial
:%d\n" , std::is_trivial::value);// true - printf("is_trivial
:%d\n" , std::is_trivial::value);// false
标准布局 (standard layout)
标准布局 (standard layout),可以通过std::is_standard_layout
判断,满足标准布局的条件有:
- 所有非静态成员有相同的访问权限
- 继承树中最多只能有一个类有非静态数据成员
- 子类的第一个非静态成员不可以是基类类型
- 没有虚函数
- 没有虚基类
- 所有非静态成员都符合标准布局类型
- struct S1{
- int i;
- };
-
- struct B1{
- void foo(){}
- };
- struct S2 : public B1{
- int i;
- };
-
- struct B2{
- int n;
- };
- struct S3 : public B2{};
-
- struct S4 : public B2{
- int i;
- };
-
- struct S5 : public B1{
- B1 b;
- int m;
- };
-
- struct S6 : public B1{
- int m;
- B1 b;
- };
-
- struct S7 : virtual public B1{};
-
- struct S8{
- S8(int val):mVal(val){}
- private :
- int mVal;
- };
-
- // Trivial but not standard-layout
- struct S9{
- public:
- int m;
- private:
- int n;
- };
-
- printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// true - printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// true - printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// true - printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// false - printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// false - printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// true - printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// false - printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// true - printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// false -
- printf("\n\n");
- printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// true - printf("is_standard_layout
:%d\n" , std::is_standard_layout::value);// true
总结
POD 类 是满足以下所有条件的类:
| (C++11 前) |
| (C++11 起) |
POD 结构体 是非联合体的 POD 类。POD 联合体 是满足 POD 类条件的联合体。
POD 属性的使用被弃用。用户代码应该期待或要求平凡或标准布局属性,或者它们两者。 | (C++20 起) |
评论记录:
回复评论: