介绍
shared_ptr是一种智能指针(smart pointer),作用有如同指针,但会记录有多少个shared_ptrs共同指向一个对象。这便是所谓的引用计数(reference counting),比如我们把只能指针赋值给另外一个对象,那么对象多了一个智能指针指向它,所以这个时候引用计数会增加一个,我们可以用shared_ptr.use_count()函数查看这个智能指针的引用计数。
下面放上c++参考手册的介绍:
具体对应模块参考链接:https://zh.cppreference.com/w/cpp/memory/shared_ptr
示例:
#include <iostream>
#include <memory> //使用shared_ptr需要include它
int main() {
//通过make_shared创建shared_ptr
std::shared_ptr<int> p1 = std::make_shared<int>();
*p1 = 78;
std::cout << "p1 = " << *p1 << std::endl;
//查看引用计数
std::cout << "p1 Reference count = " << p1.use_count() << std::endl;
//第二个shared_ptr也将在内部指向相同的指针
//这将会使引用计数变为2
std::shared_ptr<int> p2(p1);
//查看引用计数
std::cout << "p2 Reference count = " << p2.use_count() << std::endl;
std::cout << "p1 Reference count = " << p1.use_count() << std::endl;
//比较智能指针
if (p1 == p2) {
std::cout << "p1 and p2 are pointing to same pointer\n";
}
std::cout << "Reset p1" << std::endl;
//重置shared_ptr,在这种情况下,其内部不会指向内部的任何指针
//因此其引用计数将会变为0
p1.reset();
std::cout << "p1 Reference Count = " << p1.use_count() << std::endl;
//重置shared_ptr,在这种情况下,其内部将会指向一个新的指针
//因此其引用计数将会变为1
p1.reset(new int(11));
std::cout << "p1 Reference Count = " << p1.use_count() << std::endl;
//分配nullptr将取消关联指针并使其指向空值
p1 = nullptr;
std::cout << "p1 Reference Count = " << p1.use_count() << std::endl;
if (!p1) {
std::cout << "p1 is NULL" << std::endl;
}
return 0;
}
输出:
p1 = 78
p1 Reference count = 1
p2 Reference count = 2
p1 Reference count = 2
p1 and p2 are pointing to same pointer
Reset p1
p1 Reference Count = 0
p1 Reference Count = 1
p1 Reference Count = 0
p1 is NULL
下面讨论下怎样使用 std::shared_ptr自定义Deleter.
当一个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