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 = 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 |
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必须指向足够大的未构造的原始内存,能够容纳给定数量的对象 |