16.6效率与灵活性
这篇文章中c++ primer 用两种智能指针举例子
shared_ptr和unique_ptr如何指定删除器的差异实际上就是这两个类功能的差异。
我们先看一下如何定义shared_ptr的删除器
学习自csdn的网址
https://blog.csdn.net/hp_cpp/article/details/103452196
在构造函数的时候传入函数的指针:
#include <iostream>
#include <zconf.h>
#include "template.h"
using namespace std;
class Simple{
};
void deleter(Simple *)
{
cout<<"Deleter function called"<<endl;
}
// 构造函数传递自定义删除器指针
int main() {
std::shared_ptr<Simple> p1(new Simple[5],deleter);
return 0;
}
在构造函数的时候使用仿函数
我们可以这样看一个例子
class Deleter
{
public:
void operator() (Simple *x) {
std::cout << "Deleter function called" << std::endl;
delete[] x;
}
};
// 构造函数传递自定义删除器指针
int main() {
Deleter del;
std::shared_ptr<Simple> p1(new Simple[5],del);
return 0;
}
我们通过运算符重载,可以将类重载成一个类似与函数的调用方式
Deleter del;
Simple* data = new Simple();
del(data);
这样也会触发Deleter function called
lambda表达式?
这个内容真的不是很懂,不知道什么是lambda
std::shared_ptr<Sample> p3(new Sample[5], [](Sample *x) {
std::cout << "Deleter function called" << std::endl;
delete[] x;
});
第一次听说c++ 的这个东西
下面我们看一下这个lambda表达式:
原来lambda表达式就是一个闭包,也就是我们俗话说的php中的匿名函数,基本是只用一次所以也不需要函数名字,js中也有闭包
一个最简单的lambda表达式
[] {} ();
void f()
{
}
int main()
{
f();
}
如果说这个了解了那上面的函数非常容易看懂了
#include <memory>
#include <cstring>
#include <vector>
#include <stdio.h>
#include <iostream>
#include <zconf.h>
#include "template.h"
using namespace std;
class Simple{
};
// 构造函数传递自定义删除器指针
int main() {
std::shared_ptr<Simple> p1(new Simple[5],[](Simple* x){
std::cout << "Deleter function called" << std::endl;
delete[] x;
});
return 0;
}
第四种方式是使用default_delete
std::shared_ptr<Simple> p (new Simple[5],std::default_delete<Simple[]>());
我们再来看一下unique_ptr是如何指定删除器的
unique_ptr 这种就不再赘述了,只是在模板中定义出函数,然后在传入参数的时候做出实现就可以了
详细的可以参考csdn
https://blog.csdn.net/hp_cpp/article/details/103210135
总结
最后我们可以看出shared_ptr并不是直接将删除器保存为一个成员,因为删除器的类型直到运行的时候才会直到,实际上删除器的类型我们可以随时改变,unique_ptr的删除器类型在编译的时候就是知道的,unique_ptr避免了间接调用删除器的开销。通过运行时候绑定删除器,shared_ptr使用户重载删除器更加方便。