内存:常用的是static memory 和stack memory。 static memory是用来存放local static objects、类中的静态数据成员、定义在任何函数之外的变量(static中的变量在使用之前就已经分配了空间,而且其生命周期是整个程序的运行过程)。stack memory用来存放的是函数内部的非静态变量(因为栈也叫函数调用栈,存放的是函数中的auto变量,函数退出时,需要将这些变量也从栈中清除,所以其中存储的变量的生命周期只是在该函数中,因此必然存放的是该函数中的非静态变量,当然还有函数返回地址,实参列表等)。这两种内存是可以自动的分配和回收的。 另外还有一种dynamic memory是用来动态内存分配的叫做heap(堆),heap中存储的是在运行过程中才分配内存的对象,其生命周期由程序负责控制(分配和释放都是程序来完成,而非编译器)
通常在C++中申请和释放动态内存(堆)使用的是一组关键字new和delete。但是,它们是有问题的,因为,一是很难保证空间在适当的时候被释放了,二是有可能会去释放仍然有其他指针指向该内存的空间。
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,表示没有指针指向该对象,就释放掉。
例如:
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的时候,就释放掉该对象的空间。
什么时候使用动态内存:
1)不知道要申请多少个对象(比如在一个for循环中,循环次数不一定)
2)不知道对象的精确的类型(比如写了一个模板函数)
3) 需要在不同的对象之间共享数据(最常用的)
研究一下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;
}