C++智能指针: shared_ptr 实现详解
C++ 实现shared_ptr 智能指针
C++:模拟实现带weak_ptr的shared_ptr
C++ | 智能指针面试题:使用weak_ptr解决循环引用无法析构的问题
可以返回一个unique_ptr。如下代码自实现了一个unique_ptr
template
class my_unique_ptr
{
private:
_Ty* _Ptr;
public:
typedef _Ty* pointer;
typedef _Ty element_type;
my_unique_ptr(_Ty* p = nullptr) : _Ptr(p) {
cout<<"my_unique_ptr struct"< fun2(int num)
{
my_unique_ptr op(new int(num));
return op; // 临时对象的构造,调用移动拷贝构造函数
}
int main(void)
{
int x = 5;
my_unique_ptr up1 = fun2(x);
return 0;
}
参考:C++:智能指针unique_ptr详解 | 简单模拟unique_ptr部分功能 | unique_ptr使用场景
weak_ptr 设计的目的是为配合 shared_ptr 而引入的一种智能指针来协助 shared_ptr 工作, 它只可以从一个 shared_ptr 或另一个 weak_ptr 对象构造, 它的构造和析构不会引起引用记数的增加或减少。同时weak_ptr 没有重载*和->,但可以使用 lock 获得一个可用的 shared_ptr 对象(引用计数会增加1)。
std::weak_ptr 用来表达临时所有权的概念:当某个对象只有存在时才需要被访问,而且随时可能被他人删除时,可以使用 std::weak_ptr 来跟踪该对象。需要获得临时所有权时,则将其转换为 std::shared_ptr,此时如果原来的 std::shared_ptr 被销毁,则该对象的生命期将被延长至这个临时的 std::shared_ptr 同样被销毁为止。
#include
#include
#include
using namespace std;
class ClassB;
class ClassA
{
public:
ClassA() { cout << "ClassA Constructor..." << endl; }
~ClassA() { cout << "ClassA Destructor..." << endl; }
shared_ptr pb; // 在A中引用B
};
class ClassB
{
public:
ClassB() { cout << "ClassB Constructor..." << endl; }
~ClassB() { cout << "ClassB Destructor..." << endl; }
shared_ptr pa; // 在B中引用A
};
int main() {
{
std::shared_ptr fsPtr(new int(5));
std::weak_ptr fwPtr = fsPtr;
//weak_ptr不会改变shared_ptr,但是会和shared_ptr的引用保持一致
std::cout << "fsPtr use_count:" << fsPtr.use_count() << " fwPtr use_count:" << fwPtr.use_count() << std::endl;
//fwPtr.lock()后会该变shared_ptr的引用计数(+1)
//std::shared_ptr fsPtr2 = fwPtr.lock();
//std::cout << "fsPtr use_count:" << fsPtr.use_count() << " fwPtr use_count:" << fwPtr.use_count() << std::endl;
//编译报错,weak_ptr没有重载*,->操作符,因此不可直接通过weak_ptr使用对象,只能通过lock()使用shared_ptr来操作
//std::cout << " number is " << *fwPtr << std::endl;
fsPtr.reset();
if (fwPtr.expired()) // 判断所指对象是否已经被销毁
{
std::cout << "shared_ptr object has been destory" << std::endl;
}
std::shared_ptr fsPtr3 = fwPtr.lock(); //fsPtr3为NULL
std::cout << " number is " << *fsPtr3 << std::endl; //运行时中断
}
shared_ptr spa = make_shared();
shared_ptr spb = make_shared();
spa->pb = spb;
spb->pa = spa;
std::cout << "spa use_cout:" << spa.use_count() << " spb use_cout:" << spb.use_count() << std::endl; //spa: 2 spb:2
// 函数结束,思考一下:spa和spb会释放资源么? 超过作用于时引用计数减一,此时为2,减一后不为0,所以内存不释放
}
{
shared_ptr shared_p(new int(5));
weak_ptr weak_p(shared_p);
// 子线程处理函数中使用shared_p
if (int * r = shared_p.get())
{
// use *r
}
}
多线程环境中shared_ptr是可以被多个线程共享,在r被使用之前shared_p对象执行了shared_p.reset(),此时,当前线程如果继续使用r指针,势必会产生访问空地址的异常问题。这个问题需要使用weak_ptr::lock()来解决。
将上述中的判断语句改为:if (shared_ptr
lock成员获取到的shared_ptr shared_p指针,创建一个临时对象,这个临时对象同样指向shared_p,即使shared_p执了reset这样的delete引用的操作,弱引用对象仍然持有改智能指针的地址,直到r指针的生命周期结束才会释放。
参考:C++智能指针:weak_ptr实现详解
对于所有函数的参数,都不要用智能指针,尽量用普通指针。
智能指针也是一种模板类型,既然是类型,就依旧存在是栈空间还是堆空间上的问题。如果一个智能指针定义为局部变量,当它为赋值给其他智能指针变量时,它的引用计数是1,当出了局部变量作用范围后,进入智能指针类型的析构函数中,此时会引用计数会减1,然后判断引用计数是否为0,而决定真正是否释放堆空间内存。而如果这个智能指针是作为一个类的成员变量而存在,那么智能指针所管理的堆内存,是在这个类的实例析构时,析构这个成员变量时,决定是否释放智能指针所管理的堆内存的。
将裸指针作为智能指针的构造参数传入,然后将这个智能指针入到std::vector中,当调用vector的clear方法时,会触发调用到智能指针所指对象的析构函数。
#include
#include
#include
using namespace std;
class Test
{
public:
Test(int index) {
cout<<"struct test index: "< pa = std::make_shared(10);
cout<<"pa count: "< pb = pa;
cout<<"pa count: "<> testVec;
int index = 0;
Test* p = new Test(index++);
{
std::shared_ptr sp(p);
testVec.push_back(sp);
cout<