c++的POD

来源:互联网 发布:家庭光纤网络布线 编辑:程序博客网 时间:2024/06/07 03:35


POD:Plain Old Data的缩写。是c++中一个非常重要的概念。

Plain,表示了POD是个普通类型。

Old,体现了其与c的兼容

c++11中将POD划分为两个基本概念的集合。
平凡 trivial
标准布局 standard layout

平凡
一个平凡的类或结构体应该符合以下定义。
1)拥有平凡的默认构造函数(trivial constructor)和析构函数(trivial destructor)
    也就是说构造函数什么也不做。一般来说,不定义类的构造函数,编译器生成的构造函数就是平凡的构造函数。
    一旦自己定义了构造函数,即使没有参数,代码体也没有任何代码,那么构造函数也不再是平凡的了。
    例:
        struct Notrivial{Notrivial(){};};
2)拥有平凡的拷贝构造函数和移动构造函数。(参考1))
3)拥有平凡的拷贝赋值函数和移动赋值函数。(参考1))
4)不能包含虚函数以及虚基类。

c++11中可以通过类模板帮助我们判断。
头文件 type_triats
templete <typename T> struct std::is_trivial;
    例:

#include <iostream>
#include <type_traits>
class Trivial
{

};
class NoTrivial
{
    NoTrivial() {}
};

int main()
{
    std::cout << std::is_trivial<Trivial>::value << std::endl;      //1
    std::cout << std::is_trivial<NoTrivial>::value << std::endl;    //0
    system("pause");
    return 0;
}

平凡的总结
平凡是我们定义的任何操作不会对类或者结构体的构造,拷贝,赋值,析构过程产生任何的影响。



标准布局
定义:
1)所有静态成员有相同的访问权限。
    c++规定相同权限的非静态成员变量的类内的定义顺序是固定的,
    与声明时的顺序相同,不同权限的非静态成员变量的顺序,没有设置要求。
    所以要有相同的访问权限
2)在类后者结构体继承时,满足以下两种情况之一:
    1:派生类中有非静态成员,且只有一个仅包含静态成员的基类。
    2:基类有非静态成员,而派生类中没有非静态成员。
    实际上非静态成员同时出现在基类和派生类中,派生类就不属于标准布局。
    
3)类中第一个非静态成员的类型与其基类不同。
    c++标准要求类型相同的对象必须地址不同
    (基类地址及派生类中第一个非静态成员地址必须不同)
    为了区分类变量与类成员变量,
    编译器会添加1字节空间。
    c++中如果基类没有成员,标准允许派生类的第一个成员与基类共享地址。
    
4)没有虚函数和虚基类
    虚函数和虚基类,一般的编译器会添加一个vtpr(virtual table pointer)变量。

5)所有非静态成员均符合标准布局类型,其基类也符合标准布局。

c++11中可以通过类模板帮助我们判断。
头文件 type_triats
templete <typename T> struct std::is_standard_layout;

    例:
    
#include <iostream>
#include <type_traits>
class Slayout
{

};
class NoSlayout:public Slayout
{
    Slayout a;
};

int main()
{
    std::cout << std::is_standard_layout<Slayout>::value << std::endl;      //1
    std::cout << std::is_standard_layout<NoSlayout>::value << std::endl;    //0
    system("pause");
    return 0;
}

标准布局的总结

总之,标准布局就是编译器不会对我们定义的类或结构体添加额外的空间


POD判定
c++11中可以通过类模板帮助我们判断。
头文件 type_triats
templete <typename T> struct std::is_POD;


POD的好处:
1)字节赋值,代码中可以安全的使用memset和memecpy。
2)提供兼容C内存布局。
3)保证静态初始化的安全有效


掌握POD之后,对c++的内存布局就会有个大体的了解。


POD就是看起来什么样就是什么样。

例如:

struct S
{
    int a;
    int b;
    
    //函数定义
}
我们就知道这个结构体的对象模型(内存结构)是下面的这个样子的。

S x;

x     占 8字节

内部结构以及顺序是:

x.a   占 4字节     存着垃圾值

x.b   占 4字节     存着垃圾值


顺序和字节数表示的是标准布局

垃圾值表示的是平凡

所以,看起来就是C的结构体。


推荐书籍《C++ Object Model》(c++对象模型)



0 0
原创粉丝点击