c++tricks——POD与结构体声明

请看下面这个结构体定义:

struct MyStruct { 

  int i; 

  wstring str; 

  vector<wstring> strs; 

};

上面的结构休定义有问题吗?理论上说没有,但在某些情况下就可能有问题了。如下用法:

MyStruct *pMy = new MyStruct(); 

memset(pMy, 0, sizeof(MyStruct)); 

pMy->i = 100; 

pMy->str = L"leehong"; 

// Here may crash, vector is not POD, so memset() function or ZeroMemory macro do not know how to initialize the member, or it will lead some infos of pstr member lost and crash when access. 

pMy->strs.push_back(L"One");

如果这样用的话,在Debug下运行没有问题,但在Release下运行,就会在push_backCrash。这是为什么呢?这就引出下面要讲的POD了。

:实际上并不是每一种编译器编译后的程序执行都会,实测gcc就不会。

什么是POD ?

PODPlain Old Data)指的是能够像C语言中的结构体那样进行处理的一种数据类型,比如能够使用memcpy()来复制内存,使用memset()进行初始化等。

C++ 98标准中,POD实际上是受限于结构体定义中的语言特性而定义的。

struct S { int a; }; //SPOD 

struct SS { int a; SS(int aa) : a(aa) { } }; // SS不是POD

struct SSS { virtual void f(); }; // SSS不是POD

C++0x中,POD被定义为可以简单复制的,类型普通的,并且拥有可以应对多种POD原先就能支持的操作的标准变量地址布局(?)。POD的定义和以前差不多:

1)如果你所有的成员变量和基类都是POD,那么这个类型就是POD

2POD应当满足以下要求,

a)没有虚函数

b)没有虚基类

c)没有引用

d)没有多重访问

新标准对POD最大的影响就是,对于拥有不会影响数据分配布局的构造函数的数据结构,也可以算作是POD

 

关于POD详细信息,请参考官方文档:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2294.html 

Crash原因分析 

回到最上面举的那个例子,结构体初始化时,首先会调用它自动生成的默认构造函数,同时也会调用vector<wstring>的构造函数为pstr成员生成一块内存。然后我们都知道,使用结构体一般都会用memset 或 ZeroMemory函数来把结构体清成0,那么当我们调用ZeroMemory后,之前为pstr生成的内存就变成了0,这样当在后面再访问这个成员时,就会导致Crash

所以一般情况下在结构体中不要定义一些复杂的数据类型,如果无法避免,就声明这种类型的指针,因为指针肯定是一个POD的数据。

 

解决方法:

1)上面的那种方法可以把pstr换成指针类型,也就是vector<wstring>* 在调用ZeroMemory后,再对这个变量分配内存。(世纪)

2)为这个结构体写构造函数,在这个构造函数里面进行初始化,在使用时永远不要调用ZeroMemory,这样的话,struct就实际上跟class的用法一样了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值