Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说C++常用方法和技巧--POD类型,希望能够帮助你!!!。
正文之前,先请看一段代码,并思考:
1)对象a1和a2之间能否使用memcpy?
2)对象b1和b2之间能否使用memcpy?
struct A {};
struct B {};
struct A1 : A
{
A x;
int i;
};
struct A2 : A
{
B x;
int i;
};
struct B1 : A
{
int i;
A x;
};
struct B2 : A
{
int i;
B x;
};
void main()
{
A1 a1;
A2 a2;
B1 b1;
B2 b2;
std::cout << "a1和a2:" << std::endl;
std::cout <<"a1 :" << &a1 << std::endl; //
std::cout << "a2.x :" << &(a1.x) << std::endl; //
std::cout << "a2 :" << &a2 << std::endl; //
std::cout << "a2.x :" << &(a2.x) << std::endl; //
std::cout << "b1和b2:" << std::endl;
std::cout << "b1 :" << &b1 << std::endl; //
std::cout << "b1.i :" << &(b1.i) << std::endl; //
std::cout << "b2 :" << &b2 << std::endl; //
std::cout << "b2.i :" << &(b2.i) << std::endl; //
}
一 POD类型的定义
POD类型是英文中Plain Old Data的缩写。POD在C++中是一个非常重要的概念,通常用于说明一个类型的属性,尤其是用户自定义类型的属性。
POD意如其名。Plain,表示了POD类型是个普通的类型,在C++中常见的类型都有这样的属性,而不像一些存在着虚函数虚继承的类型那么特别。而Old类型则体现了其与C的兼容性,比如可以用最老的memcpy()函数进行复制,使用memset()进行初始化等。具体地, POD类型划分为两个基本概念的合集,即:平凡的(trivial)和标准布局的(standar layout)。
1 平凡的
1) 拥有平凡的默认构造函数(trivial constructor)和析构函数(trivial destructor)
2) 拥有平凡的拷贝构造函数(trivial copy constructor)和移动构造函数(trivial move constructor)
3) 拥有平凡的拷贝赋值运算符(trivial assignment operator)和移动赋值运算符(trivial move operator)
4) 不能包含虚函数和虚基类
判断类型是否是平凡的,可用标准库中的is_trivial方法,头文件<type_traits>
template <typename T> struct std::is_trivial;
2 标准布局
1) 所有非静态成员有相同的访问权限(public,private,protected)
2) 在类或结构体继承时,满足下列两种情况之一:
3) 类中第一个非静态成员的类型与其基类不同
4) 没有虚函数和虚基类
5) 所有非静态数据成员均符合标准布局类型,其基类也符合标准布局
判断类型是否是平凡的,可用标准库中的is_standard_layout方法,头文件<type_traits>
template <typename T> struct std::is_standard_layout;
二 POD类型的作用
我们先来运行一下文章开头的代码,看下执行结果:
从结果中看出: b1.i和b1的地址相同,b2.i和b2的地圸相同;a1.x和a1的地址不同,a2.x和a2的地址相同。
用下图来示意下a1、a2、b1、b2的内存结构:
因此,b1和b2间可以用memcpy,a1和a2是不可以的。
特别说明:不同的编译器所得结果不同,以上为gcc测试效果,在msvc中测试,a1.x和a1的地址是相同的。
对于POD而言,就是平凡的和标准布局的两个方面,判别方法:
template <typename T> struct std::is_pod;
//is_pod::value<T>==true等同于,is_standard_layout::value<T>==true 并且is_trivial::value<T>==true.
查看A1、A2、B1、B2是否为POD类型:
std::cout << "A1:" << std::is_pod<A1>::value << std::endl; // 输出 0
std::cout << "A2:" << std::is_pod<A2>::value << std::endl; // 输出 1
std::cout << "B1:" << std::is_pod<B1>::value << std::endl; // 输出 1
std::cout << "B2:" << std::is_pod<B2>::value << std::endl; // 输出 1
因此,A1不是POD类型,至于A1不符合前面讲的哪一条定义,自己对着定义找去吧。
使用POD好处:
今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
上一篇
已是最后文章
下一篇
已是最新文章