到目前为止,我们只使用了static和stack内存,前者用于存储static变量和全局变量,
后者用来存放函数体内部的nonstatic对象。
除了static和stack之外,程序还提供了内存池可使用,它称为free store或者heap。
heap用来提供动态申请的内存空间。
12.1 Dynamic Memory and Smart Pointers
----------------------------------------------------------------
new用来申请动态内存,delete用来删除动态内存。
动态内存的管理,很容易变得一片狼藉,要么我们忘了释放它(内存泄露),要么释放早了(还会访问)。
新的C++库提供了smart pointer来管理动态内存:
shared_ptr //允许多个指针同时访问
unique_ptr //只允许一个指针
weak_ptr //是shared_ptr的对象的weak reference
#include <memory>
和vector一样,smart pointer也是templates,需要额外的信息才能被初始化。
比如:
shared_ptr<string> p1;
shared_ptr<list<int>> p2;
p1 = make_shared<string>("hello");
再比如下面的代码
p = make_shared<string>("hello");
auto q1 = p;
auto q2(p);
cout << p.use_count() << endl;
cout << q1.use_count() << endl;
cout << q2.use_count() << endl;
执行结果:
[marianna@localhost Debug]$ ./hello2
3
3
3
这是因为p、q1、q2都指向了同一个对象。
如果make_shared的对象没有任何shared_ptr指向它,它就会被释放。
如果将share_ptrs放置在容器中,make sure将没用的元素erase掉。
我们现在定义一个自己的类strBlob,用于存储collection类型,这里直接借用vector。
我们不能直接在strBlob中存储vector,因为某个strBlob对象释放时,vector也会被释放,
而我们希望所有的strBlob共用一个vector。
此时可以动态申请vector,并且使用shared_ptrs来管理它。
new用来申请动态内存,可以是const的;
delete用来删除动态内存,必须是动态内存指针或者是nullptr指针。
动态内存的管理极易出错:
* 忘记释放动态内存,这个问题被称为内存泄露,极难检测。
* 使用已经被释放的内存。
* 两次删除同一个动态内存。
因此,请使用smart pointer来管理动态内存吧!!!
一般来说,不要混用plain指针和smart指针。
一般来说,不要使用两个独立的smart指针指向同一个内存地址。
总的来说,动态内存的管理就使用smart指针就好了。
有些“打开”+“关闭”配对的操作,也可以使用smart指针实现:
void f(destination &d /* other parameters */)
{
connection c = connect(&d);
shared_ptr<connection> p(&c, end_connection);
// use the connection
// when f exits, even if by an exception, the connection will be properly closed
}
使用smart指针的惯例:
* 不要用build-in指针值去初始化或者reset多个smart指针。
* 不要删除get()的返回指针。
* 不要使用get()去初始化或者reset其他smart指针。
* 使用smart指针去管理非动态内存时,记得传入delete函数。
unique_ptr拥有它的唯一对象,因此它不能被复制,也不能被赋值。
unique_ptr可以使用reset或者release来转移它的对象。
unique_ptr的release函数,仅仅是切断指针和对象的联系,而不会释放对象。
12.2 Dynamic Arrays
----------------------------------------------------------------
大部分时候,我们可以使用vector或者其他容器来实现动态存储的功能,
在必要的时候,可以采用allocator类。
int *pia = new int[get_size()];
这种方式有它的限制,即pia并不知道array的类型,因此也不能使用属于array的方法。
delete [] pa;
删除动态矩阵时,必须使用它。
使用unique_ptr管理动态矩阵:
unique_ptr<int[]> up(new int[10]);
up.release();
使用shared_ptr管理动态矩阵:
我们必须提供自定义的delete函数,另外通过get()指针而不是下标来访问矩阵。
虽然我们可以使用new来申请动态矩阵的内存,但是最好还是使用allocator类。
allocator的申请和构造步骤是分开的。
allocator是一个template,因此它需要额外的参数。
比如下面的代码:
int n = 20;
allocator<string> alloc;
auto const p = alloc.allocate(n);
12.3 Using the Library: A Text-Quary Program
----------------------------------------------------------------
例子就不看了,练习的时候根据实际情况编写自己的程序。
文章评论(0条评论)
登录后参与讨论