提示:浅浅记录一下智能指针–unique_ptr
一、unique_ptr是什么?
std::unique_ptr 是一个模板类,它提供了对动态分配对象的独占所有权(即没有其他智能指针可以同时拥有同一个对象的所有权)。 当 std::unique_ptr 被销毁时,它所指向的对象也会被自动删除。
二、使用
创建方式
代码如下:
#include <memory>
std::unique_ptr<类,析构解释器> ptr(new 类)
std::unique_ptr 的自定义删除器(析构解释器)
自定义删除器是指在使用智能指针(如 std::unique_ptr、std::shared_ptr)时,可以通过自定义的方式来指定在智能指针的资源释放时所执行的操作,其作用是在智能指针释放资源时执行某些特定的操作,例如释放动态分配的内存、关闭文件、释放锁等。
在 C++ 中,自定义删除器可以是一个函数对象,也可以是一个函数指针,其签名("签名"是指函数的特定特征,通常由函数的返回类型、函数名、参数类型和参数顺序组成。)应该与智能指针所管理的资源类型的析构函数相匹配(这意味着删除器函数应该接受与资源类型的析构函数相同的参数,并且没有返回值 或返回 void ),例如,如果智能指针管理的资源类型具有以下析构函数:
~ResourceType(); //类的析构函数
//那么与之匹配的自定义删除器函数的签名应该是:
void deleteResource(ResourceType* ptr);
//或者,如果自定义删除器是一个函数对象,则其 operator() 函数的签名应该是:
void operator()(ResourceType* ptr);
在这两种情况下,删除器函数都接受一个指向资源类型的指针作为参数,并且不返回任何值。
三、附上完整代码
#include <memory>
#include <iostream>
#include<functional>
#include <string>
class Foo{
public:
Foo(std::string name, int class_num ){
this->name = name;
this->class_num = class_num;
std::cout << "creat Foo" << std::endl;
}
Foo(){
std::cout << "creat Foo" << std::endl;
}
~Foo(){
std::cout << "delete Foo" << std::endl;
}
void show_info()
{
std::cout << "I am " << name << "in the class " << class_num << std::endl;
}
private:
std::string name;
int class_num;
};
struct delete_foo{
void operator()(Foo* f){
std::cout << "do something before delete the foo" << std::endl;
delete f;
}
};
void delete_f(Foo* f){
std::cout << "do something before delete the foo" << std::endl;
delete f;
}
int main(){
//Foo f;
// Foo* f = new Foo;
// delete f;
std::unique_ptr<Foo,delete_foo> f(new Foo("xiaocai",4));
f->show_info();
//std::unique_ptr<Foo,void(*)(Foo*)> f1(new Foo,delete_f);
return 0;
}
参考写法自 B站up 小柴ai 的现代C++频道 ,添加了使用函数指针的自定义删除器(注释部分)。在 std::unique_ptr 中,如果传递的自定义删除器是一个函数指针,则它被视为指向一个普通的函数,该函数接受一个指针参数并执行相应的删除操作。因此,在 std::unique_ptr<Foo, void()(Foo)> 中,void()(Foo) 表示一个函数指针类型,指向的函数接受 Foo* 类型的参数。
而在 std::unique_ptr<Foo, delete_foo> 中,delete_foo 是一个类类型,它实现了函数调用运算符 operator(),这意味着它是一个可调用对象(也称为函数对象或仿函数)。在这种情况下,当 std::unique_ptr 需要删除指针时,它会调用 delete_foo 的函数调用运算符,不需要显式地传递函数对象的参数(个人认为更方便)。
因此,当使用函数指针作为删除器时,需要明确指定指向函数的类型,而当使用函数对象作为删除器时,则不需要传递额外的参数。