POD类型的几点总结

    前段时间看《Inside the C++ Object Model》时,对trival和non-trival两个词就没大搞明白,今天在wikipedia上看C++ 11词条又碰到了,稍微深入了一点,发现这里门道还真不少。关键词POD是理解trival关键的点,找了些博客,论文,看了一晚上,总算豁然开朗了。

    C++ Language Point:POD Types 中对POD的定义写得很清楚,当然,这篇文章写于1999年,符合当时的C++98规范,到了C++11,其中一些表述就不太准确了,最后我会指出,以下是参照原文的概括:

    POD是Plain Old Data的缩写,它的存在是为了在数据类型上兼容C。POD可以简单分为两类:标量类型(scalar types)和POD类类型(POD class types)以及两者各自的const/volatile版本(cv-qualified versions)。scalar types很好理解,我的看法就是可以在维度上理解为一个点,或者说是一个原子,包括算术类型(整型,浮点)、枚举、指针(普通指针:normal pointer和成员指针:pointer-to-menber)。而POD class types,我理解这是一个迭代的概念,如果一个类只包含POD数据,那这个类就是POD,以此类推,如果一个类只包含POD数据,或者POD类,那么它也属于POD。POD class types可以是struct(或者class,一样的),也可以是union,必须满足:

1.所有的non-static data menber都是POD类型且都是public的。

2.没有自定义的constructor、destructor、copy assignment operator。(不准确)

3.non-static data不能是引用、成员指针。(在C++11中这条已经不准确了)。

4.没有虚函数。

5.没有基类。

  这五条概括的很全面了,如果再提炼一下的话,那就是,去掉C++中OO的封装(第一条)、继承(第五条)、多态(第四条)。构造函数只能是trival的。

MSDN  的解释:

A constructor for a class Ty is trivial if:

it is an implicitly declared default constructor

the class Ty has no virtual functions

the class Ty has no virtual bases

all the direct bases of the class Ty have trivial constructors

the classes of all the non-static data members of class type have trivial constructors

the classes of all the non-static data members of type array of class have trivial constructors

    因此明确几点:trival必须是implicit,即使你显示声明一个空的默认构造函数,它也就成了non-trival的了;在构造对象时,除了初始化POD menber data 外,还要有其他的工作,比如有虚函数就会有额外的虚函数表的改写,有虚基类就会有虚基类表的改写,这些都会导致构造函数增加代码,变为non-trival。对于赋值操作来说,trival版本可以理解为“啥也没做”,等价于raw memory copying 函数memcpy,即Bitwise Copy Semantics。

    回到POD的讨论,为什么non-static menber data不能是引用类型呢?回想C++ Primer 5th里的说法,引用不是一种对象,声明时必须绑定到特定的对象上。下例:


#include <iostream>
using namespace std;
class A{
public:
int &a;

}
int main(){
cout << (has_trivial_constructor<A>()?"has_trival_constructor":"not has_trival_constructor") << endl;
    cout << (is_pod<A>::value ? "is a pod" : "is not a pod") << endl;

return 0;

}
output:
not has_trival_constructor
is not a pod

请按任意键继续. . .
 

上面的例子通过编译,间接说明编译器对引用类型进行了初始化,由一个implicit non-trival constructor完成。

    第三条说noe-static menber data 不能是pointer-to-menber,在C++11中是不准确的。

   

#include <iostream>
using namespace std;
class A{
public:
    int a;
    int A::*p;
 }
int main(){
    cout << (has_trivial_constructor<A>()?"has_trival_constructor":"not has_trival_constructor") << endl;
    cout << (is_pod<A>::value ? "is a pod" : "is not a pod") << endl;
    
    return 0;

}

output:
has_trival_constructor
is a pod.

 

    以下是POD类型在布局、初始化、拷贝、取址上的特点

expressionPOD type Tnon-POD type T
 new Tnot initializeddefault-initialized
 new T()always default-initialized
 new T(x)always initialized via a constructor

Thus, an object (or an array) of non-POD type is always guaranteed initialization,while an instance (or an array) of a POD type may be left uninitialized.

Other POD-related C++ characteristics include the following:

  1. Layout
    • The bytes constituting a POD object are contiguous [§1.8, ¶5].
    • "POD-struct ... types are layout-compatible if they have the same numberof members, and corresponding members (in order) have layout-compatibletypes" [§9.2, ¶14].
    • POD-union ... types are layout-compatible if they have the same numberof members, and corresponding members (in any order) have layout-compatibletypes" [§9.2, ¶15].
  2. Initialization
    • A non-const POD object declared with no initializer has an "indeterminateinitial value" [§8.5, ¶9].
    • Default initialization of a POD object is zero initialization [§8.5,¶5].
    • A static POD object declared with an initializer is givenits initial value:
      • if local, "before its block is first entered" [§6.7, ¶4]; else
      • if non-local, "before any dynamic initialization takes place" [§3.6.2,¶1].
  3. Copying
    • The bytes constituting a POD object can be copied (e.g., via memcpy())
      • to a sufficiently large array of char or unsignedchar and back again without changing the object's value [§3.9,¶2], or
      • to another object of the same POD-type, in which case the second object'svalue will be the same as that of the first [§3.9, ¶3].
    • Any POD type may be used as the "character" type in the standard's templatedstring classes [§21, ¶1].
  4. Addressing
    • The address of a POD object can be an address constant expression (or partof one) [§5.19, ¶4], while a reference to a POD member can bea reference constant expression [§5.19, ¶5].
    • "A pointer to a POD-struct object, suitably converted using a reinterpret_cast,points to its initial member ... and vice versa" [§9.2, ¶17].

stack overflow:http://stackoverflow.com/questions/4178175/what-are-aggregates-and-pods-and-how-why-are-they-special/7189821#7189821

                              http://stackoverflow.com/questions/4178175/what-are-aggregates-and-pods-and-how-why-are-they-special/4178176#4178176

fnal:http://www.fnal.gov/docs/working-groups/fpcltf/Pkg/ISOcxx/doc/POD.html




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值