原创 【博客大赛】《C++ Primer》学习笔记(30)Dynamic Memory

2016-4-19 22:59 879 4 4 分类: MCU/ 嵌入式 文集: Qt和Cpp

到目前为止,我们只使用了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
----------------------------------------------------------------
例子就不看了,练习的时候根据实际情况编写自己的程序。

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
4
关闭 站长推荐上一条 /3 下一条