热度 4
2016-4-19 22:59
882 次阅读|
0 个评论
到目前为止,我们只使用了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_ptrstring p1; shared_ptrlistint p2; p1 = make_sharedstring("hello"); 再比如下面的代码 p = make_sharedstring("hello"); auto q1 = p; auto q2(p); cout p.use_count() endl; cout q1.use_count() endl; cout q2.use_count() endl; 执行结果: $ ./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_ptrconnection 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 ; 这种方式有它的限制,即pia并不知道array的类型,因此也不能使用属于array的方法。 delete up(new int ); up.release(); 使用shared_ptr管理动态矩阵: 我们必须提供自定义的delete函数,另外通过get()指针而不是下标来访问矩阵。 虽然我们可以使用new来申请动态矩阵的内存,但是最好还是使用allocator类。 allocator的申请和构造步骤是分开的。 allocator是一个template,因此它需要额外的参数。 比如下面的代码: int n = 20; allocatorstring alloc; auto const p = alloc.allocate(n); 12.3 Using the Library: A Text-Quary Program ---------------------------------------------------------------- 例子就不看了,练习的时候根据实际情况编写自己的程序。