shared_ptr 使用详解 (C++11)
熟悉了unique_ptr 后,其实我们发现unique_ptr 这种排他型的内存管理并不能适应所有情况,有很大的局限!如果需要多个指针变量共享怎么办?
如果有一种方式,可以记录引用特定内存对象的智能指针数量,当复制或拷贝时,引用计数加1,当智能指针析构时,引用计数减1,如果计数为零,代表已经没有指针指向这块内存,那么我们就释放它!这就是 shared_ptr 采用的策略!
构造函数
shared_ptr sp ; //空的shared_ptr,可以指向类型为T的对象 shared_ptr sp1(new T()) ;//定义shared_ptr,同时指向类型为T的对象 shared_ptr<T[]> sp2 ; //空的shared_ptr,可以指向类型为T[的数组对象 C++17后支持 shared_ptr<T[]> sp3(new T[]{…}) ;//指向类型为T的数组对象 C++17后支持 shared_ptr sp4(NULL, D()); //空的shared_ptr,接受一个D类型的删除器,使用D 释放内存 shared_ptr sp5(new T(), D()); //定义shared_ptr,指向类型为T的对象,接受一个D 类型的删除器,使用D删除器来释放内存
初始化
方式一 构造函数 shared_ptrr up1(new int(10)); //int(10) 的引用计数为1 shared_ptrr up2(up1); //使用智能指针up1构造up2, 此时int(10) 引用计数为2
方式二 使用make_shared 初始化对象,分配内存效率更高 make_shared函数的主要功能是在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr; 用法: make_shared<类型>(构造类型对象需要的参数列表); shared_ptr p4 = make_shared(2); //多个参数以逗号’,'隔开,最多接受十个 shared_ptr p4 = make_shared(“字符串”);
demo 代码(一)
#include <iostream>
#include <stdio.h>
#include <memory>
using namespace std
;
class Person
{
public
:
Person(int v
)
{
this
->no
= v
;
cout
<< "Construct" << no
<< endl
;
}
~Person()
{
cout
<< "Destruct" << no
<< endl
;
}
private
:
int no
;
};
int main(void)
{
shared_ptr
<Person
> sp1
;
shared_ptr
<Person
> sp2(new
Person(2));
cout
<< "sp1 ref_counter: " << sp1
.use_count() << endl
;
cout
<< "sp2 ref_counter: " << sp2
.use_count() << endl
;
sp1
= sp2
;
cout
<< "after sp1 = sp2, sp2 ref_counter: " << sp2
.use_count() << endl
;
shared_ptr
<Person
> sp3(sp1
);
cout
<< "after sp3(sp1), sp2 ref_counter: " << sp2
.use_count() << endl
;
system("pause");
return 0;
}
运行结果:
demo 代码(二)
#include <iostream>
#include <stdio.h>
#include <memory>
using namespace std
;
class Person
{
public
:
Person(int v
)
{
this
->no
= v
;
cout
<< "Construct" << no
<< endl
;
}
~Person()
{
cout
<< "Destruct" << no
<< endl
;
}
private
:
int no
;
};
int main(void)
{
shared_ptr
<Person
> sp1
;
shared_ptr
<Person
> sp2(new
Person(2));
cout
<< "sp1 ref_counter: " << sp1
.use_count() << endl
;
cout
<< "sp2 ref_counter: " << sp2
.use_count() << endl
;
sp1
= sp2
;
cout
<< "after sp1 = sp2, sp2 ref_counter: " << sp2
.use_count() << endl
;
shared_ptr
<Person
> sp3(sp1
);
cout
<< "after sp3(sp1), sp2 ref_counter: " << sp2
.use_count() << endl
;
shared_ptr
<Person
[]> sp4(new Person
[5]{ 3,4,5,6,7 });
system("pause");
return 0;
}
运行结果:
demo 代码(三)
#include <iostream>
#include <stdio.h>
#include <memory>
using namespace std
;
class Person
{
public:
Person(int v
)
{
this->no
= v
;
cout
<< "Construct" << no
<< endl
;
}
~Person()
{
cout
<< "Destruct" << no
<< endl
;
}
private:
int no
;
};
class DestructPerson
{
public:
void operator()(Person
* pt
)
{
cout
<< "DestructPerson" << endl
;
delete pt
;
}
};
int main(void)
{
shared_ptr
<Person
> sp1
;
shared_ptr
<Person
> sp2(new Person(2));
cout
<< "sp1 ref_counter: " << sp1
.use_count() << endl
;
cout
<< "sp2 ref_counter: " << sp2
.use_count() << endl
;
sp1
= sp2
;
cout
<< "after sp1 = sp2, sp2 ref_counter: " << sp2
.use_count() << endl
;
shared_ptr
<Person
> sp3(sp1
);
cout
<< "after sp3(sp1), sp2 ref_counter: " << sp2
.use_count() << endl
;
shared_ptr
<Person
[]> sp4(new Person
[5]{ 3,4,5,6,7 });
shared_ptr
<Person
> sp8(new Person(8), DestructPerson());
shared_ptr
<Person
> sp9
;
sp9
= make_shared
<Person
>(9);
cout
<< "after sp9 = mke_shared<Person>(9), sp9 ref_counter: " << sp9
.use_count() << endl
;
system("pause");
return 0;
}
运行结果:
demo 代码(四)
#include <iostream>
#include <stdio.h>
#include <memory>
using namespace std
;
class Person
{
public:
Person(int v
)
{
this->no
= v
;
cout
<< "Construct" << no
<< endl
;
}
~Person()
{
cout
<< "Destruct" << no
<< endl
;
}
private:
int no
;
};
class DestructPerson
{
public:
void operator()(Person
* pt
)
{
cout
<< "DestructPerson" << endl
;
delete pt
;
}
};
int main(void)
{
shared_ptr
<Person
> sp1
;
shared_ptr
<Person
> sp2(new Person(2));
cout
<< "sp1 ref_counter: " << sp1
.use_count() << endl
;
cout
<< "sp2 ref_counter: " << sp2
.use_count() << endl
;
sp1
= sp2
;
cout
<< "after sp1 = sp2, sp2 ref_counter: " << sp2
.use_count() << endl
;
shared_ptr
<Person
> sp3(sp1
);
cout
<< "after sp3(sp1), sp2 ref_counter: " << sp2
.use_count() << endl
;
shared_ptr
<Person
[]> sp4(new Person
[5]{ 3,4,5,6,7 });
shared_ptr
<Person
> sp8(new Person(8), DestructPerson());
shared_ptr
<Person
> sp9
;
sp9
= make_shared
<Person
>(9);
cout
<< "after sp9 = mke_shared<Person>(9), sp9 ref_counter: " << sp9
.use_count() << endl
;
shared_ptr
<Person
> sp10
;
Person
* p10
= new Person(10);
sp9
.reset(p10
);
cout
<< "after sp9.reset(p10), sp9 ref_counter: " << sp9
.use_count() << endl
;
system("pause");
return 0;
}
执行:
demo 代码(五)
#include <iostream>
#include <stdio.h>
#include <memory>
using namespace std
;
class Person
{
public
:
Person(int v
)
{
this
->no
= v
;
cout
<< "Construct" << no
<< endl
;
}
~Person()
{
cout
<< "Destruct" << no
<< endl
;
}
int no
;
};
class DestructPerson
{
public
:
void operator()(Person
* pt
)
{
cout
<< "DestructPerson" << endl
;
delete pt
;
}
};
int main(void)
{
shared_ptr
<Person
> sp1
;
shared_ptr
<Person
> sp2(new
Person(2));
cout
<< "sp1 ref_counter: " << sp1
.use_count() << endl
;
cout
<< "sp2 ref_counter: " << sp2
.use_count() << endl
;
sp1
= sp2
;
cout
<< "after sp1 = sp2, sp2 ref_counter: " << sp2
.use_count() << endl
;
shared_ptr
<Person
> sp3(sp1
);
cout
<< "after sp3(sp1), sp2 ref_counter: " << sp2
.use_count() << endl
;
shared_ptr
<Person
[]> sp4(new Person
[5]{ 3,4,5,6,7 });
shared_ptr
<Person
> sp8(new
Person(8), DestructPerson());
shared_ptr
<Person
> sp9
;
sp9
= make_shared
<Person
>(9);
cout
<< "after sp9 = mke_shared<Person>(9), sp9 ref_counter: " << sp9
.use_count() << endl
;
shared_ptr
<Person
> sp10
= sp9
;
Person
* p10
= new
Person(10);
sp9
.reset(p10
);
cout
<< "after sp9.reset(p10), sp9 ref_counter: " << sp9
.use_count() << endl
;
std
::swap(sp9
, sp10
);
cout
<< "交换后, sp9: " << sp9
->no
<< "sp10: " << sp10
->no
<< endl
;
sp9
.swap(sp10
);
cout
<< "sp9. swap(sp10) 交换后, sp9: " << sp9
->no
<< " sp10: " << sp10
->no
<< endl
;
system("pause");
return 0;
}
运行结果:
赋值
shared_ptrr up1(new int(10)); //int(10) 的引用计数为1 shared_ptr up2(new int(11)); //int(11) 的引用计数为1 up1 = up2;//int(10) 的引用计数减1,计数归零内存释放,up2共享int(11)给up1, int(11) 的引用计数为2
主动释放对象
shared_ptrr up1(new int(10)); up1 = nullptr ;//int(10) 的引用计数减1,计数归零内存释放 或 up1 = NULL; //作用同上
重置
up.reset() ; //将p重置为空指针,所管理对象引用计数 减1 up.reset(p1); //将p重置为p1(的值),p 管控的对象计数减1,p接管对p1指针的管控 up.reset(p1,d); //将p重置为p(的值),p 管控的对象计数减1并使用d作为删除器
交换
std::swap(p1,p2); //交换p1 和p2 管理的对象,原对象的引用计数不变 p1.swap(p2); //同上
使用陷阱
shared_ptr作为被管控的对象的成员时,小心因循环引用造成无法释放资源!
#include <stdio.h>
#include <iostream>
#include <string>
#include <memory>
#include <vector>
using namespace std
;
class girl;
class boy
{
public:
boy()
{
cout
<< "boy construct!" << endl
;
}
~boy()
{
cout
<< "boy destruct!" << endl
;
}
void set_girl_friend(shared_ptr
<girl
>& g
)
{
this->girl_friend
= g
;
}
private:
shared_ptr
<girl
> girl_friend
;
};
class girl
{
public:
girl()
{
cout
<< "girl construct !" << endl
;
}
~girl()
{
cout
<< "girl destruct!" << endl
;
}
void set_boy_friend(shared_ptr
<boy
>& b
)
{
this->boy_friend
= b
;
}
private:
shared_ptr
<boy
> boy_friend
;
};
void use_trap()
{
shared_ptr
<girl
> sp_girl(new girl());
shared_ptr
<boy
> sp_boy(new boy());
sp_girl
->set_boy_friend(sp_boy
);
sp_boy
->set_girl_friend(sp_girl
);
}
int main()
{
use_trap();
system("pause");
return 0;
}
结语:
这时间, 快高考了!!!
时间: 2020-07-03