当一个shared_ptr对象超出作用域时,其析构函数被调用,在析构函数中,将其引用计数减1,如果引用计数的值变为0,则删除关联的原始指针。
要删除析构函数中的内部原始指针,默认情况下,shared_ptr调用delete()函数,即
delete Pointer;
但是,我们在析构函数中并不总是要使用delete函数,还可能有其他的需求。
如果shared_ptr指向一个数组而不是一个简单的指针
std::shared_ptr<int> p3(new int[12]);
在其析构函数中,shared_ptr将会调用
delete
函数来删除int数组,而正确的方式是使用
delete []
增加定制deleter到shared_ptr
在这种情况下,我们可以将一个回调传递给shared_ptr的构造函数,该构造函数将会在其析构函数中被调用
定制Deleter作为函数指针
//函数调用接收到的指针上的delete[]
void deleter(Sample *x){
std::cout<<"DELETE FUNCTION CALLED\n";
delete[] x;
}
在shared_ptr的构造函数中传递函数指针,以提供自定义的deleter
//使用定制deleter创建sharedptr
std::shared_ptr<Sample> p3(new Sample[12, deleter);
检查完整的例子如下:
#include <iostream>
#include <memory>
struct Sample {
Sample() {
std::cout << "CONSTRUCTOR\n";
}
~Sample() {
std::cout << "DESTRUCTOR\n";
}
};
//在接收到的指针上调用delte[]的函数
void deleter(Sample* x) {
std::cout << "DELETER FUNCTION CALLED\n";
delete[] x;
}
int main() {
//使用定制的deleter创建shared_ptr
std::shared_ptr<Sample> p3(new Sample[12], deleter);
return 0;
}
输出:
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
DELETER FUNCTION CALLED
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
自定义Deleter作为lambda函数或函数对象
我们也可以将Function对象和Lambda函数作为回调函数来附加
class Deleter {
public:
void operator ()(Sample* x) {
std::cout << "DELETER FUNCTION CALLED\n";
delete[] x;
}
};
//函数对象作为deleter
std::shared_ptr<Sample> p3(new Sample[12], Deleter());
//lambdah函数作为deleter
std::shared_ptr<Sample> p4(new Sample[12], [](Sample* x)
std::cout<<"DELETER FUNCTION CALLED\n";
delete[] x;
});
当我们不需要删除内存空间,只需要释放内存或资源给pool时,可能会有其他的情况。
查看一个虚拟实现 Memory Pool和Custom Deletor的例子:
#include <iostream>
#include <memory>
struct Sample {
};
//内存池虚拟类型的实现
template<typename T>
class MemoryPool {
public:
T* AquireMemory() {
std::cout << "AQUIRING MEMORY\n";
return (new T());
}
void ReleaseMemory(T* ptr) {
std::cout << "RELEASE MEMORY\n";
delete ptr;
}
};
int main() {
std::shared_ptr<MemoryPool<Sample>> memoryPoolPtr = std::make_shared<
MemoryPool<Sample> >();
std::shared_ptr<Sample> p3(memoryPoolPtr->AquireMemory(),
std::bind(&MemoryPool<Sample>::ReleaseMemory, memoryPoolPtr,
std::placeholders::_1));
return 0;
}
输出:
AQUIRING MEMORY
RELEASE MEMORY