C++-CC++中联合体必须是POD类型的

C++-CC++中联合体必须是POD类型的

清晨说ぺ晚安 发布于 2016-12-10 字数 233 浏览 1359 回复 2

先看一段代码:

template < typename T >
struct must_be_pod
{
...
static void constraints()
{
union
{
T T_is_not_POD_type;
};
}
...
};

如果你对这篇文章有疑问,欢迎到本站 社区 发帖提问或使用手Q扫描下方二维码加群参与讨论,获取更多帮助。

扫码加入群聊

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

晚风撩人 2017-08-12 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

虐人心 2017-05-31 1 楼

首先说第二个问题。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() ,而不用一个个的赋值。