文章目录
动态分配的对象存储在堆上,生存期与作用域无关,只有当显式地被释放时,这些对象才会销毁。
动态内存与智能指针
智能指针:负责在合适的时机自动释放所指向的对象
- shared_ptr:允许多个
shared_ptr
指向同一个对象 - unique_ptr:独占所指向的对象
- weak_ptr:弱引用,不占引用计数,指向
shared\_ptr
所指向的对象
shared_ptr
make_shared
在动态内存中构造一个对象,并返回指向它的shared_ptr
shared_ptr<int> p1 = make_shared<int>(42);
auto p2 = make_shared<string>(10, '9');
auto p3 = make_shared<int>(); // 值初始化
auto p4(p3); // p4和p3指向同一个对象
引用计数
引用计数增加:拷贝shared_ptr时,例如用一个shared_ptr初始化另一个shared_ptr,作为函数实参,作为函数的返回值…
引用计数减少:让shared_ptr指向其它的对象,shared_ptr被销毁(离开作用域等)…
当引用计数为0时,shared_ptr就会自动释放自己所管理的对象
管理shared_ptr的容器,如果不再需要某些元素,应该用erase删除,使shared_ptr被销毁
直接管理内存
new
string *ps = new string; // 默认初始化为空string
Sales_data *p = new Sales_data; // 使用默认构造函数初始化
/* 内置类型 默认初始化和值初始化有区别 */
int *pi1 = new int; // 默认初始化 pi1的值未定义
int *pi2 = new int(); // 值初始化为0
delete
传递给delete的指针必须指向动态分配的内存,或者空指针。释放一块并非由new分配的内存,或者将同一块内存释放多次,行为是未定义的。delete后,指针仍然保存着已释放的动态内存的地址。
shared_ptr和new结合使用
shared_ptr<int> p1 = new int(1024); // 错误,接受指针参数的智能指针构造函数是explicit的
shared_ptr<int> p2(new int(1024));
默认情况下,一个用来初始化智能指针的普通指针必须指向动态内存,因为智能指针默认使用delete释放它所关联的对象。也可以自定义释放操作。
unique_ptr
某个时刻只能有一个unique_ptr指向某个对象,当unique_ptr被销毁时,它所指向的对象也会被销毁。unique_ptr不支持拷贝或赋值。
unique_ptr<string> p1(new string("abc"));
unique_ptr<string> p2(p1.release()); // release将p1置为空,指针所有权转移给p2
unique_ptr<string> p3(new string(""));
p2.reset(p3.release()); // reset释放了p2原来指向的内存
weak_ptr
指向由一个shared_ptr管理的对象,将weak_ptr绑定到一个shared_ptr不会改变引用计数。
auto p = make_shared<int>(42);
weak_ptr<int> wp(p);
if (shared_ptr<int> np = wp.lock()) // 检查weak_ptr指向的对象是否存在
{
// ...
}
动态数组
int *pia1 = new int[10](); // 10个值初始化为0的int
int *pia2 = new int[10]{0,1,2,3,4,5,6,7,8,9};
delete [] pia1;
/* unique_ptr管理动态数组 */
unique_ptr<int[]> up(new int[10]);
up.release(); // 自动用delete[]销毁其指针
/* shared_ptr管理动态数组 */
/* 必须提供自定义的删除器 */
shared_ptr<int> sp(new int[10], [](int *p) {delete[] p;});
sp.reset(); // 使用自定义的lambda释放数组
allocator类
new将内存分配和对象构造组合在一起,当分配大块内存时,可能希望将内存分配和对象构造分离
使用allocator分配未初始化的内存,使用时再构造对象
allocator<string> alloc;
auto const p = alloc.allocate(n); // 分配n个未初始化的string
auto q = p;
alloc.construct(q++, "abc"); // 构造对象
alloc.destroy(--q); // 销毁对象
alloc.deallocate(p, n); // 释放内存