第 12 章 动态内存(1)

2019-04-21  本文已影响0人  cb_guo

12.1 动态内存与智能指针

12.1.1 shared_ptr 类
shared_ptr 和 unique_ptr 都支持的操作
shared_ptr<T> 空指针,可以指向类型为 T 的对象
unique_ptr<T>

p             将 p 作为一个条件判断,若 p 指向一个对象,则为 true

*p            解引用 p ,获得它指向的对象

p->mem        等价于 (*p).mem

p.get()       返回 p 中保存的指针。要小心使用,若智能指针释放了其对象,返回的指针所指向的对象也就消失了

swap(p, q)    交换 p 和 q 中的指针
p.swap(q)
shared_ptr 独有操作
make_shared<T>(args)  返回一个 shared_ptr,指向一个动态分配的类型为 T 的对象。使用 args 初始化此对象

shared_ptr<T>p(q)     p 是 shared_ptr q 的拷贝;此操作会递增 q 中的计数器。q中的指针必须能转换成T*

p = q                 p 和 q 都是 shared_ptr ,所保存的指针必须能相互转换。
                      此操作会递减 p 的引用计数,递增 q 的引用计数;
                      若 p 的引用计数为 0 ,则将其管理的原内存释放

p.unique()            若 p.use_count() 为 1,返回 true,否则返回 false

p.use_count()         返回与 p 共享对象的智能指针数量;可能很慢,主要用于调试
make_shared 函数

最安全的分配和使用动态内存的方法是调用一个名为 make_shared 的标准库函数。此函数在动态内存中分配一个对象并初始化它,返回指向此对象的 shared_ptr 。与智能指针一样,make_shared 也定义在头文件 memory 中

// 指向一个值为42 的 int 的 shared_ptr
shared_ptr<int> p3 = make_shared<int>(42);

// p4 指向一个值为 "9999999999" 的 string
shared_ptr<string> p4 = make_shared<string>(10,'9');

// p5 指向一个值初始化的 int ,即值为 0 
shared_ptr<int> p5 = make_shared<int>();

// 当然,我们通常用 auto 定义一个对象来保存 make_shared 的结果,这种方式比较简单
// p6 指向一个动态分配的空 vector<string>
auto p6 = make_shared<vector<string>>();
shared_ptr 的拷贝和赋值
auto p = make_shared<int>(42);   p 指向的对象只有 p 一个引用者
quto q(p);                       p q 指向相同的对象,此对象有两个引用者
auto r = make_shared<int>(42);  r 指向的 int 只有一个引用者
r = q;    给 r 赋值,令它指向另一个地址
          递增 q 指向的对象的引用计数
          递减 r 原来指向的对象的引用计数
          r 原来指向的对象已没有引用者,会自动释放
shared_ptr 自动销毁所管理的对象
shared_ptr 还会自动释放相关联的内存
// factory 返回一个 shared_ptr ,指向一个动态分配的对象
shared_ptr<Foo> factory(T arg){
     // 恰当处理 arg
     // shared_ptr 负责释放内存
     return make_shared<Foo>(arg);
}
void use_factory(T arg){
    shared_ptr<Foo> p = factory(arg);
    // 使用 p
}   // p 离开了作用域,它指向的内存会被自动释放掉
shared_ptr<Foo> use_factory(T arg){
    shared_ptr<Foo> p = factory(arg);
    // 使用 p
    return p;  // 当我们返回 p 时,引用计数进行了递增操作
}  // p 离开了作用域,但它指向的内存不会被释放掉
12.1.3 直接管理内存

使用 new 和 delete 管理动态内存存在的三个常见问题

空悬指针

delete 一个指针之后,指针值就变为无效了。虽然指针已经无效了,但在很多机器上仍然保存着(已经释放了的)动态内存的地址。在 delete 之后,指针就变成了人们所说的空悬指针,即,指向一块曾经保存数据但现在已经无效的内存的指针

上一篇 下一篇

猜你喜欢

热点阅读