notes/ch12.md
对象的生命周期:
static对象在第一次使用前分配,在程序结束时销毁。对象的内存位置:
static对象、类static对象、定义在任何函数之外的变量。static对象。new:在动态内存中为对象分配空间并返回一个指向该对象的指针。delete:接受一个动态对象的指针,销毁该对象,并释放与之关联的内存。shared_ptr和unique_ptr都支持的操作:
| 操作 | 解释 |
|---|---|
shared_ptr<T> sp unique_ptr<T> up | 空智能指针,可以指向类型是T的对象 |
p | 将p用作一个条件判断,若p指向一个对象,则为true |
*p | 解引用p,获得它指向的对象。 |
p->mem | 等价于(*p).mem |
p.get() | 返回p中保存的指针,要小心使用,若智能指针释放了对象,返回的指针所指向的对象也就消失了。 |
swap(p, q) p.swap(q) | 交换p和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共享对象的智能指针数量;可能很慢,主要用于调试。 |
new动态分配和初始化对象。
new无法为分配的对象命名(因为自由空间分配的内存是无名的),因此是返回一个指向该对象的指针。int *pi = new int(123);bad_alloc的异常。delete将动态内存归还给系统。
delete后的指针称为空悬指针(dangling pointer)。new和delete管理动态内存存在三个常见问题:
delete内存。定义和改变shared_ptr的其他方法:
| 操作 | 解释 |
|---|---|
shared_ptr<T> p(q) | p管理内置指针q所指向的对象;q必须指向new分配的内存,且能够转换为T*类型 |
shared_ptr<T> p(u) | p从unique_ptr u那里接管了对象的所有权;将u置为空 |
shared_ptr<T> p(q, d) | p接管了内置指针q所指向的对象的所有权。q必须能转换为T*类型。p将使用可调用对象d来代替delete。 |
shared_ptr<T> p(p2, d) | p是shared_ptr p2的拷贝,唯一的区别是p将可调用对象d来代替delete。 |
p.reset() | 若p是唯一指向其对象的shared_ptr,reset会释放此对象。若传递了可选的参数内置指针q,会令p指向q,否则会将p置空。若还传递了参数d,则会调用d而不是delete来释放q。 |
p.reset(q) | 同上 |
p.reset(q, d) | 同上 |
reset)多个智能指针delete get()返回的指针。get()返回的指针,记得当最后一个对应的智能指针销毁后,你的指针就无效了。new分配的内存,记住传递给它一个删除器。unique_ptr指向一个给定的对象。auto_ptr:老版本,具有unique_ptr的部分特性。特别是,不能在容器中保存auto_ptr,也不能从函数返回auto_ptr。unique_ptr操作:
| 操作 | 解释 |
|---|---|
unique_ptr<T> u1 | 空unique_ptr,可以指向类型是T的对象。u1会使用delete来是释放它的指针。 |
unique_ptr<T, D> u2 | u2会使用一个类型为D的可调用对象来释放它的指针。 |
unique_ptr<T, D> u(d) | 空unique_ptr,指向类型为T的对象,用类型为D的对象d代替delete |
u = nullptr | 释放u指向的对象,将u置为空。 |
u.release() | u放弃对指针的控制权,返回指针,并将u置空。 |
u.reset() | 释放u指向的对象 |
u.reset(q) | 令u指向q指向的对象 |
u.reset(nullptr) | 将u置空 |
weak_ptr是一种不控制所指向对象生存期的智能指针。shared_ptr管理的对象,不改变shared_ptr的引用计数。shared_ptr被销毁,对象就会被释放,不管有没有weak_ptr指向该对象。weak_ptr操作:
| 操作 | 解释 |
|---|---|
weak_ptr<T> w | 空weak_ptr可以指向类型为T的对象 |
weak_ptr<T> w(sp) | 与shared_ptr指向相同对象的weak_ptr。T必须能转换为sp指向的类型。 |
w = p | p可以是shared_ptr或一个weak_ptr。赋值后w和p共享对象。 |
w.reset() | 将w置为空。 |
w.use_count() | 与w共享对象的shared_ptr的数量。 |
w.expired() | 若w.use_count()为0,返回true,否则返回false |
w.lock() | 如果expired为true,则返回一个空shared_ptr;否则返回一个指向w的对象的shared_ptr。 |
new一个动态数组:
int *p = new int[size];delete一个动态数组:
delete [] p;unique_ptr和数组:
unique_ptr不支持成员访问运算符(点和箭头)。| 操作 | 解释 |
|---|---|
unique_ptr<T[]> u | u可以指向一个动态分配的数组,整数元素类型为T |
unique_ptr<T[]> u(p) | u指向内置指针p所指向的动态分配的数组。p必须能转换为类型T*。 |
u[i] | 返回u拥有的数组中位置i处的对象。u必须指向一个数组。 |
allocator类定义在头文件memory中,帮助我们将内存分配和对象构造分离开。allocator是一个模板。allocator<string> alloc;标准库allocator类及其算法:
| 操作 | 解释 |
|---|---|
allocator<T> a | 定义了一个名为a的allocator对象,它可以为类型为T的对象分配内存 |
a.allocate(n) | 分配一段原始的、未构造的内存,保存n个类型为T的对象。 |
a.deallocate(p, n) | 释放从T*指针p中地址开始的内存,这块内存保存了n个类型为T的对象;p必须是一个先前由allocate返回的指针。且n必须是p创建时所要求的大小。在调用deallocate之前,用户必须对每个在这块内存中创建的对象调用destroy。 |
a.construct(p, args) | p必须是一个类型是T*的指针,指向一块原始内存;args被传递给类型为T的构造函数,用来在p指向的内存中构造一个对象。 |
a.destroy(p) | p为T*类型的指针,此算法对p指向的对象执行析构函数。 |
allocator伴随算法:
| 操作 | 解释 |
|---|---|
uninitialized_copy(b, e, b2) | 从迭代器b和e给定的输入范围中拷贝元素到迭代器b2指定的未构造的原始内存中。b2指向的内存必须足够大,能够容纳输入序列中元素的拷贝。 |
uninitialized_copy_n(b, n, b2) | 从迭代器b指向的元素开始,拷贝n个元素到b2开始的内存中。 |
uninitialized_fill(b, e, t) | 在迭代器b和e执行的原始内存范围中创建对象,对象的值均为t的拷贝。 |
uninitialized_fill_n(b, n, t) | 从迭代器b指向的内存地址开始创建n个对象。b必须指向足够大的未构造的原始内存,能够容纳给定数量的对象。 |
memory中。