内存:经常使用的是static memory 和stack memory。 static memory是用来存放local static objects、类中的静态数据成员、定义在任何函数以外的变量(static中的变量在使用以前就已经分配了空间,并且其生命周期是整个程序的运行过程)。stack memory用来存放的是函数内部的非静态变量(由于栈也叫函数调用栈,存放的是函数中的auto变量,函数退出时,须要将这些变量也从栈中清除,因此其中存储的变量的生命周期只是在该函数中,所以必然存放的是该函数中的非静态变量,固然还有函数返回地址,实参列表等)。这两种内存是能够自动的分配和回收的。 另外还有一种dynamic memory是用来动态内存分配的叫作heap(堆),heap中存储的是在运行过程当中才分配内存的对象,其生命周期由程序负责控制(分配和释放都是程序来完成,而非编译器)
ios
一般在C++中申请和释放动态内存(堆)使用的是一组关键字new和delete。可是,它们是有问题的,由于,一是很难保证空间在适当的时候被释放了,二是有可能会去释放仍然有其余指针指向该内存的空间。
c++
library中在memory头部定义了了两个smart pointer来自动地管理动态内存。shared_ptr(还定义了一个weak_ptr), unique_ptr。smart pointer也和vector同样是模板。用做类型建立对象的时候须要加上, 如shared_ptr p1; //shared_ptr that can point at a string
安全
shared_ptr: 容许多个指针指向相同的对象。最安全的方法是调用函数make_shared 进行分配。如shared_ptr p2 = make_shared(4). shared_ptr定义的建立的对象有一个指针reference count,不管何时拷贝shared_ptr的指针的时候,count都加1. 当给shared_ptr的指针赋了新值或者shared_ptr失效的时候,count减1。 当count等于0的时候,shared_ptr指向的对象自动释放空间。因此关键是建立的对象中维持了一个引用计数,来追踪全部指向该段空间的指针。若是计数的值为0,表示没有指针指向该对象,就释放掉。函数
例如:this
auto r = make_shared<char>(4); r = q; //after this, system will release the four bytes memory.
为何可以自动释放内存: 必须提到constructor和destructor,constructor是分配内存,初始化对象的时候使用的,destructor是释放空间,摧毁对象用的。在shared_ptr中有一个destructor,该destructor记录了对象的引用计数,当引用计数为0的时候,就释放掉该对象的空间。spa
何时使用动态内存:指针
1)不知道要申请多少个对象(好比在一个for循环中,循环次数不必定)c++11
2)不知道对象的精确的类型(好比写了一个模板函数)code
3) 须要在不一样的对象之间共享数据(最经常使用的)orm
研究一下vector(stl中定义的一个容器)中使用的是哪里的内存? 按照7的三个使用动态内存的条件,vector应该属于不知道要多少空间来存放对象。所以,应该属于动态内存方面的问题。 那么应该如何地建立和释放内存呢?vector中有两个函数,size()和capacity(),size()表示容器中有多少个数据,capacity()表示容器中最多放置多少个数据。另外可使用clear来释放容器中的数据。可是根据下面的实验能够看出,使用clear只是释放掉了容器中的数据项,可是并无释放容器占有的空间。即容器在不断地伸长地过程当中不断地申请的新的空间并无释放。仍然被这个容器占用。可使用shrink_to_fit() 使得占有的空间等于容器中实际的数据项,或者使用reserve(n)使得分配至少n的元素的空间。(可是根据C++ primer中所说,shrink_to_fit()只是一个请求,并不保证必定释放掉空间,另外shrink_to_fit是在c++11中提出来的。 若是不支持C++11,可使用建立一个临时的匿名容器再进行swap的方法来强制释放掉空间,由于交换以后,临时的匿名容器会当即被析构,而原来的容器则等于匿名容器的大小,也就是0)
#include <iostream> #include <vector> using namespace std; int main(){ vector it; double a[100] for(int i=0; i<100; i++){ a[i] = i; } cout << "数据项个数: " << it.size() << "容器占有空间为: " << it.capacity() << endl; for(int i=0;i<100;i++){ it.push_back(a[i]); } cout << ""数据项个数:" << it.size() << "容器占有空间为: " << it.capacity() << endl; it.clear(); cout << "clear以后数据项个数: " << it.size() << "clear以后容器占有空间为: " << it.capacity() << endl; it.shrink_to_fit(); //or vector().swap(it); cout << "swap以后数据项个数: " << it.size() << "swap以后容器占有空间为: " << it.capacity() << endl; return 0; }