一 unique_ptr
1 unique_ptr删除器
unique_ptr和shared_ptr一样,默认删除器都是使用delete,所以当我们创建的是一个数组或者文件这些时,显然delete是无法有效回收的。
删除器是一个可调用对象,其中可调用对象可以是普通函数,或者重载了()括号的类,或者lambda表达式等等。
unique_ptr删除器比shared_ptr多了一步,先要在类型模板参数中传递进去类型名,然后在参数中再给具体的其函数名。
void mydeleter(string *pdel)
{
delete pdel;
pdel = nullptr;
//可以打印日志
cout<<"mydeleter"<<endl;
}
void test19(){
// a.1
typedef void(*fp)(string *);
unique_ptr<string, fp> ps1(new string("good luck"), mydeleter);
//a.2
using fp2 = void(*)(string *);
unique_ptr<string, fp2> ps2(new string("good luck"), mydeleter);
//a.3
typedef decltype(mydeleter)* fp3; //decltype()返回函数类型void(string *),所以要加*,现在fp3应该是void *(string *)
unique_ptr<string, fp3> ps3(new string("good luck"), mydeleter);
//a.4
unique_ptr<string, decltype(mydeleter)*> ps4(new string("good luck"), mydeleter);
//a.5,lambda表达式,可以理解成operator()类类型对象
auto mydella = [](string *pdel)->void{
delete pdel;
pdel = nullptr;
cout<<"mydella"<<endl;
};
//注意,lambda表达式mydella被编译器理解成对象(即ps5的参2),所以我们类型不能加*,否则地址与对象不匹配
//而上面的函数名mydeleter代表是首地址,需要加*地址符号进行匹配。(对象不是对象,&对象才是地址)
unique_ptr<string, decltype(mydella)> ps5(new string("good luck"), mydella);
}
指定删除器额外说明
- 1)shared_ptr:就算两个shared_ptr指定的删除器不同,指向他们指向的对象相同,那么他们属于同一个类型。可以放到同一个容器中。
- 2)unique_ptr:指定unique_ptr中的删除器会影响unique_ptr类型。所以,从灵活性上来讲,shared_ptr更灵活。unique_ptr如果删除器不同,那么就等于整个unique_ptr类型不同,这种类型不同的unique_ptr智能指针是没法放到同一个容器中的。
2 尺寸问题
当我们在上面代码添加求智能指针的所占字节数,如下:
//开头先求原指针所占字节数
string *str = NULL;
cout<<"未加删除器的指针所占字节数="<<sizeof(str)<<endl;
//然后在每个ps下面各自求出对应智能指针的所占字节数。这里只列出一个。
int ilen = sizeof(ps1);
cout << "ps1的所占字节数=" << ilen << endl;
结果:注意我的是64位下测试,所以原指针所占字节数为8,若是VS的32位下,原指针占4字节。
上面结果明显看到,lambda表达式,尺寸没有变化,其余都发现变化。
所以可以总结:
如果你增加了自己的删除器,则unique_ptr的尺寸可能增加,也可能不增加。具体如下:
- 1)用lambda表达式,尺寸没有变化。
- 2)定义一个函数作为删除器,尺寸发生变化。增加字节的对效率有影响。shared_ptr不管你指向什么删除器,shared_ptr的尺寸大小都是裸指针的2倍。
3 智能指针的总结
目前开发我们只需要用到shared_ptr, unique_ptr已经足够,weak_ptr基本不需要使用,它更多时候是给那些开发标准库的人使用。
然后shared_ptr, unique_ptr的选择主要看下面的区别:
- 1)如果程序要是用多个指向同一个对象的指针,应选择shared_ptr。
- 2)如果程序不需要多个指向同一个对象的指针,应该首选unique_ptr。
讲到本篇,智能指针的所有知识点结束,我以前也总结过智能指针,但是不够全面,目前这8篇已经非常全面了,智能指针各种使用场合,和语法都包含进去,总的来说写这八篇文章还是有点难度的,原因是C++的新语法越来越看不懂,有点吃力。完结。