C++-CC++中联合体必须是POD类型的
先看一段代码:
template < typename T >
struct must_be_pod
{
...
static void constraints()
{
union
{
T T_is_not_POD_type;
};
}
...
};
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
POD本质上是与c兼容的类型结构, 可以使用memset初始化, memcpy复制
POD结构(POD-struct)是一个聚合类,它没有以下类型的非静态数据成员:指向成员的指针、非POD结构、非POD联合(或以上类型的数组),或它们的引用,并且没有用户自定义的拷贝赋值运算符,也没有用户自定义的析构函数。
类似的,POD联合(POD-union)是一个聚合联合,它没有以下类型的非静态数据成员:指向成员的指针、非POD结构、非POD联合(或以上类型的数组),或它们的引用,并且没有用户自定义的拷贝赋值运算符,也没有用户自定义的析构函数。
POD类(POD class)是一个类,它要么是POD结构,要么是POD联合。以下几种是POD:
1、所有基本数据类型
2、一个class或者struct,它不包含虚函数,没有虚基类,每一个数据成员都是POD,且所有的父类(如果存在的话)都是POD
3、POD数组
4、由POD组成的union
POD可以包含非虚成员函数,当然也可以包含构造函数和(非虚)析构函数,因为这些东东都不影响对象布局。
下面这个类,它不需要copy ctor就可以拷贝构造,但不是POD:
struct S
{
std::string str; // std::string内部有指针,使用memcpy时执行浅拷贝
};
C++11中对POD的定义
当class/struct是极简的(trivial)、属于标准布局(standard-layout),以及他的所有非静态(non-static)成员都是POD时,会被视为POD。
一个极简的类别或结构符合以下定义:
极简的默认建构式。这可以使用默认建构式语法,例如SomeConstructor() = default;
极简的复制建构式,可使用默认语法(default syntax)
极简的赋值运算子,可使用默认语法(default syntax)
极简的解构式,不可以是虚拟的(virtual)
一个标准布局(standard-layout)的类别或结构符合以下定义:
只有非静态的(non-static)资料成员,且这些成员也是符合标准布局的型别
对所有non-static成员有相同的存取控制(public, private, protected)
没有虚拟函式
没有虚拟基础类别
只有符合标准布局的基础类别
没有和第一个定义的non-static成员相同型别的基础类别
若非没有带有non-static成员的基础类别,就是最底层(继承最末位)的类别没有non-static资料成员而且至多一个带有non-static成员的基础类别。基本上,在该类别的继承体系中只会有一个类别带有non-static成员。
参考: http://www.fnal.gov/docs/working-groups/fpcltf/Pkg/ISOcxx/doc/POD.html
首先说第二个问题。C++98标准9.5节第1条说明:“如果一个类具有非平凡的构造函数、非平凡的拷贝构造函数、非平凡的析构函数,或者非平凡的赋值操作符,那么其对象不能作为联合的成员”。这里的“非平凡”我的理解是指“非默认的”,比如自定义的非默认构造函数,虚析构函数等,不过,如果自定义了一个接受单个整型参数的非显式构造函数(non-explicit constructor)和一个可用的拷贝构造函数,那么它也是POD类型的。
POD的意思是“plain-old-data”,必须满足以下条件:
将组成它的一个对象的各个字节拷贝到一个字节数组中,然后再将它们重新拷贝回原来的对象所占的存储区中,此时该对象应该仍具有它原来的值;
对于任何POD类型T, 如果有两个指针分别指向不同的T对象obj1和obj2,此时如果使用memcpy()函数将obj1的值拷贝进obj2中,obj2就应该跟obj1具有相同的值;
在平常编写C++代码时,POD类型最重要的应用应该就是将一些变量封装到结构体中,使这些变量在函数参数、函数返回值时,可以直接用结构体来表示,而不用写很长一串的函数参数,并且保证赋值可以很方便地直接使用 memcpy() ,而不用一个个的赋值。