memset函数的使用及注意事项

来源:互联网 发布:数据库管理软件做什么 编辑:程序博客网 时间:2024/05/15 02:26
   
    本文也是对自己对工作经验中的一个小小的总结,主要上memset及清0的一些小小的技巧,哈,这些都是很基础的,牛人可以视而不见,就当我没说,我也只是这段时间闲着,所以干脆顺便写点小心得,献丑了。

   

优化:尽量用memset将一个数组设置清零(带虚类除外),而不是通过for循环逐个置0

   

    下面这个例子,大家可以参考:3D游戏编程大师技巧。本文其实重点是memset,原因是在工作中,用的比较多。

 

    例如:要清空一个float f[10000],应该用memset(f,0,sizeof(float) * 10000);

    而不是: for(int i=0; i<10000; ++i) f[i] = 0;

    当然,还可以用内嵌汇编的形式:

      _asm
      {
       mov edi, f;       // edi指向数组地的目标内存的起始处
       mov ecx, 1000/4;  // 循环次数或移动次数
       mov eax, 0;       // 每一次移动32位数,都置0
       rep stosd;        // 移动数据
         

 

    哈,这个准则有个前提,那就是带虚的类除外,原因是,memset将类清空,有可能将虚表也给置0了。

有可能是因为:类的创建分:栈上和堆上。

   如果在栈上,那么栈对象的虚函数调用可能会在静态时确定,从而绕过虚表。所以不会出错。

   但堆上就一定会出错,下面给出测试代码:

 

********************************************************************
** 创建人: 蔡国武
** 日  期: 2011/5/27 14:21
** 版  本: 1.0
** 描  述: 代码性能优化与技巧----测试
           测试:在堆和栈上创建的带虚类的memset清零后,虚表是否失效

** 应  用: 尽量用memset将一个数组设置清零(带虚类除外),而不是通过for循环逐个置0
 
**************************** 修改记录 ******************************
** 修改人:
** 日  期:
** 描  述:
********************************************************************/

 

class CMemsetVirtualTest // 测试 带虚类,被memset为0后,虚表是否失效
{
public:
    CMemsetVirtualTest()
    {
        memset(this,0,sizeof(CMemsetVirtualTest));
    }
  
    virtual void NormalFun()
    {
        cout<<"test: NormalFun()  虚表指针有效"<<endl;
    }

    virtual ~CMemsetVirtualTest()
 {
  cout<<"test: ~CMemsetVirtualTest()  虚表指针有效"<<endl;
 }
}; 

void testFun1() // 测试:栈上建立的对象
{
 CMemsetVirtualTest Ctest;
 Ctest.NormalFun();
}

void testFun2() // 测试:堆上建立的对象
{
 CMemsetVirtualTest* Ptest = new CMemsetVirtualTest();
 Ptest->NormalFun(); // 到这里一定会暴掉
 delete Ptest;       // 如果屏蔽上句,到这里也一定会暴掉
}

 

int main()
{

 CMemsetVirtualTest Ctest;// 测试:栈上建立的对象

 Ctest.NormalFun();// 测试正常:

 

 CMemsetVirtualTest* Ptest = new CMemsetVirtualTest();  // 测试:堆上建立的对象
 Ptest->NormalFun(); // 到这里一定会暴掉
 delete Ptest;       // 如果屏蔽上句,到这里也一定会暴掉
}

 

   即:

   在C++中,涉及虚技术的类,他的对象内存区块中就不单纯是用户定义这个类时看上去的那些数据结构,编译器会在当中安插一些数据或代码,用来实现响应的虚技术.于是当你用memset函数时会把这些编译器安插的东西冲掉, 程序执行结果变得未知. 这时候如果拷贝对象C++会使用memberwise拷贝, 此时编译器既拷贝用户定义的数据结构,还会对支持虚技术的相关设施进行适当的修改.
   如果对象没有用到虚技术, 那么就可以使用memset,就跟正常情况一样,可以逐位拷贝.

原创粉丝点击