c++:动态内存与智能指针(3)

1. weak_ptr

weak_ptr是一种不控制所指向对象生存期的智能指针,它指向由一个shared_ptr管理的对象。将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放。即使有weak_ptr指向对象,对象也还是会被释放。
就是weak_ptr和shared_ptr关系不大的意思

weak_ptr
weak_ptr< T > w空weak_ptr可以指向类型为T的对象
weak_ptr< T > w(sp)与shared_ptr sp指向相同对象的weak_ptr。T必须能转换为sp指向的类型
w = pp可以是一个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
auto p = make_shared<int>(42);
weak_ptr<int> wp(p);
cout << *p << endl;
cout << *wp.lock() << endl;//由于对象可能不存在,所以必须调用ock来访问对象

2. new和数组

//调用get_size确定分配多少个int
int *pia = new int[get_size()];//pia指向第一个int
typedef int arrT[42];//arrT表示42个int的数组类型
int *p = new arrT;//分配一个42个int的数组;p指向第一个int

当用new分配一个数组时,我们并未得到一个数组类型的对象,而是得到一个数组元素类型的指针。即使我们使用类型别名定义了一个数组类型,new也不会分配一个数组类型的对象。
由于分配的内存并不是一个数组类型,因此不能对动态数组调用begin或end,也不能用for语句来处理(所谓的)动态数组中的元素

2.1 动态分配一个空数组是合法的
size_t = get_size();//get_size返回需要的元素的数目
int *p = new int[n];//分配数组保存元素
for(int *q = p;q != p+n;++q)
//...

即使get_size返回0,代码仍能正常运行,因为调用new[0]是合法的

char arr[0];//错误:不能定义长度为0的空数组
char *cp = new char[0]//正确:但cp不能解引用

此种指针类似尾后指针(尾后迭代器),不能解引用

2.2 释放动态数组

为了释放动态数组,我们使用一种特殊形式的delete
——在指针前加上一个方括号:

delete p;//p必须指向一个动态分配的对象或为空
delete [] pa;//pa必须指向一个动态分配的数组或为空

2.3 智能指针和动态数组

可以使用unique_ptr管理动态数组

//up指向一个包含10个未初始化int的数组
unique_ptr<int[]> up(new int[10]);
up.release();//自动用delete销毁其指针

尽量别用shared_ptr管理动态数组,这玩意还得自己写删除器

3. allocator类

new将内存分配和对象构造组合在一起可能会导致不必要的浪费。allocator类解决了这个问题。

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*的指针,指向一块原始内存;arg被传递给类型为T的构造函数,用来在p指向的内存中构造一个对象
a.destroy( p )p为T*类型的指针,此算法对p指向的对象执行析构函数
//一个例子
 auto n = 100;
 allocator<string> alloc;//可以分配string的allocator对象
 auto const p = alloc.allocate(n);//分配n个未初始化的string
 auto q = p;//q指向最后构造的元素之后的位置
 //cout << *q << endl;
 alloc.construct(q++);//*q为空字符串
 //cout << *q << endl;
 alloc.construct(q++, 10, 'c');//*q为cccccccccc
 cout << *q << endl;
 alloc.construct(q++,"hi");//*q为hi!
 cout << *q << endl;
 while (q != p)
 	alloc.destroy(--q);//释放我们真正构造的string
 alloc.deallocate(p, n);//释放内存给系统
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必须指向足够大的未构造的原始内存,能够容纳给定数量的对象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值