Stack vs. Heap

来源:互联网 发布:2016欧洲杯数据统计 编辑:程序博客网 时间:2024/04/28 12:59

 

栈比堆更有效率

要注意的是:
如果你的对象需要在其他函数中使用就不能在栈上分配。因为在栈上的对象会随着

函数的返回而消亡。
如果你需要一个可变长度的对象也不能在栈上分配,因为栈上分配的内存必须在编

译的时候就要确定。
当你定义一个对象(比如类的实例)在栈上。当这个对象生命期结束的时候,会自

动调用析构函数来打扫内存。相反,如果你是在堆上分配的,那么你必须警觉内存

泄露的问题!

举个例子:


  1. <code> 
  2.   // ** Stack Allocation ** 
  3.   { 
  4.       // Allocate MyClass instance on the stack 
  5.       MyClass c; 
  6.       … use c 
  7.   } // c destructor called by C++ compiler 
  8.   // ** Heap Allocation ** 
  9.   { 
  10.       // Allocate on the heap 
  11.       MyClass * ptrC = new MyClass(); 
  12.       …use heap-allocated instance 
  13.       ptrC->DoSomething(…); 
  14.   } // Destructor *not* called here! Memory leak! 
  15.    // Must do an explicit delete ptrC; 
  16. </code> 

总之,如果你只是一个小的对象,你可以在栈上分配内存。相反,如果你的对象要

占用大量内存。你就应该在堆上分配。

同时注意到,C++ 的STL容器类 (比如 std::vector)是可以分配在栈上的。但是

请注意,其内部实现中的内存分配实际上是在堆上进行的。比如:
std::vector<double>someData(1000)
这个向量对象(someData)是分配在栈上的。没错吧?可是 ,其内部数据(这1000个

double类型的值)是通过std::vector的内部机制分配在堆上的。

 

总之,如果一个对象需要在其局部作用域之外存在,就需要在堆上分配内存。反之

,就在栈上分配内存才合适。
另外,当我们在堆上分配内存的时候,使用一些标准库里面的类型(CArray or

std::vector )是一个比较好的选择。因为有其生成的对象的析构函数保证在其离开

作用域的时候正常的调用,而不会产生内存泄露等严重问题。

  1. Case 1:
  2. Poor strategy: 
  3. CMyDIalog * dlg = new CMyDialog; 
  4. dlg->DoModal(); 
  5. //… 
  6. delete dlg; 
  7. Good strategy:
  8. CMyDialog dlg; 
  9. dlg.DoModal(); 
  10. //… 
  11. Case 2:
  12. Poor strategy: 
  13. LPBYTE b = new BYTE[size]; 
  14. //… 
  15. delete b; 
  16. Good strategy:
  17. CByteArray b; 
  18. b.SetSize(size); 
  19. or 
  20. std::vector<BYTE> b; 
  21. b.resize(size); 
  22. Case 3:
  23. Poor strategy: 
  24. LPDWORD d = new DWORD
  25. *d = 0; 
  26. Function1(d); 
  27. //… 
  28. delete d; 
  29. Good strategy:
  30. DWORD d = 0; 
  31. Function1(&d); 
  32. // … 
  33. Case 4:
  34. Poor strategy(failing strategy): 
  35. TCHAR buffer[COMPILE_TIME_SIZE]; 
  36. read_stuff_into(buffer); 
  37. PostMessage(WM_USE_DATA, (WPARAM)buffer); 
  38. Good strategy: 
  39. TCHAR buffer[COMPILE_TIME_SIZE]; 
  40. read_stuff_into(buffer); 
  41. SendMessage(WM_USE_DATA, (WPARAM)buffer); 
  42. or
  43. TCHAR * buffer = new TCHAR[COMPILE_TIME_SIZE]; 
  44. read_stuff_into(buffer); 
  45. PostMessage(WM_USE_DATA, (WPARAM)buffer);  //delete the pointer in the message handler


 
上述例子表明了这些在函数中声明的对象在其离开函数作用域之后仍然是需要存在

的。

如果你没有必要把内存分配在堆上那就不做

如果你需要对象存在更长的时间,请放在堆上。

原创粉丝点击