1.概要
- std::shared_ptr是一种智能指针(smart pointer),作用有如同指针,但会记录有多少个shared_ptrs共同指向一个对象。这便是所谓的引用计数(reference counting)。一旦最后一个这样的指针被销毁,也就是一旦某个对象的引用计数变为0,这个对象会被自动删除。这在非环形数据结构中防止资源泄露很有帮助。
- std::weak_ptr 是一种智能指针,通常不单独使用,只能和 shared_ptr 类型指针搭配使用,可以视为 shared_ptr 指针的一种辅助工具。借助 weak_ptr 类型指针可以获取 shared_ptr 指针的一些状态信息,比如有多少指向相同的 shared_ptr 指针、通过expired()判断shared_ptr 指针指向的堆内存是否已经被释放等等,还可以解决shared_ptr 循环引用的问题。
#include <iostream>
using namespace std;
class A
{
public:
void fun() {
cout << "A fun\n";
}
};
int main()
{
//创建两个指针
shared_ptr<A> sh_ptr = std::make_shared<A>();
//实验:基本使用
sh_ptr.get()->fun();
//结果:A fun 证明智能指针基本功能有效,哈哈,当然有效,这是一个指针最基本的保证
//实验:拷贝一个指针看,看看指针的引用数量是多少
shared_ptr<A> sh_ptr2 = sh_ptr;
//结果:2 证明有两引用,证明weak_ptr的基本功能:可查看引用数量
//实验:我把两个指针都取出来,那么是否意味着我的这两个指针也指向了对象呢?
A* a = sh_ptr.get();
A* b = sh_ptr2.get();
//实验:查看两个指针指向的地址是否是同一个
cout <<"a addr:"<< a <<" b addr:"<< b << endl;
//结果: a addr:0000029E9D623250 b addr:0000029E9D623250 两个指针指向同一个地址
std::weak_ptr<A> wp(sh_ptr);
//实验:查看这时候有几个指针指向对象 理论推断有可能4个 sh_ptr,sh_ptr2,a,b?
// sh_ptr,sh_ptr2 和 a,b 有啥差别呢,a,b 是真正的指针,但是sh_ptr,sh_ptr2本质上不是指针,是一个管理指针的对象而已。所以还是有差别的。
// 那么我如果delete a 或者 b 会有什么结果呢?
std::cout << wp.use_count()<<"\n";//有两个引用 但实际上应该是4个,因为A* a B* b还有两个
// 结果:2 证明这个引用的控制和 a b 没有关系。
// 那么有就是说明了,如果我们使用了智能指针,就不要在使用A* a A* b 这种用法了,
// 或者说用了,但是不要 delete,因为这个对象已经被智能制造管理了,我们就不要对他的生命周期有任何的干预了,由智能制指针负责就好了。
delete a;
//结果:可以删除但是会报异常
//删除一个对象后,指针的引用数量会有什么变化呢?
std::cout << wp.use_count() << "\n";
// 结果:因为前面报了异常,所以这个结果也就没法确认了。
std::cout << "Hello World!\n";
}
2.代码
// ConsoleApplication3.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
using namespace std;
class A
{
public:
void fun() {
cout << "A fun\n";
}
};
int main()
{
//创建两个指针
shared_ptr<A> sh_ptr = std::make_shared<A>();
//实验:基本使用
sh_ptr.get()->fun();
//结果:A fun 证明智能指针基本功能有效,哈哈,当然有效,这是一个指针最基本的保证
//实验:拷贝一个指针看,看看指针的引用数量是多少
shared_ptr<A> sh_ptr2 = sh_ptr;
//结果:2 证明有两引用,证明weak_ptr的基本功能:可查看引用数量
//实验:我把两个指针都取出来,那么是否意味着我的这两个指针也指向了对象呢?
A* a = sh_ptr.get();
A* b = sh_ptr2.get();
//实验:查看两个指针指向的地址是否是同一个
cout <<"a addr:"<< a <<" b addr:"<< b << endl;
//结果: a addr:0000029E9D623250 b addr:0000029E9D623250 两个指针指向同一个地址
std::weak_ptr<A> wp(sh_ptr);
//实验:查看这时候有几个指针指向对象 理论推断有可能4个 sh_ptr,sh_ptr2,a,b?
// sh_ptr,sh_ptr2 和 a,b 有啥差别呢,a,b 是真正的指针,但是sh_ptr,sh_ptr2本质上不是指针,是一个管理指针的对象而已。所以还是有差别的。
// 那么我如果delete a 或者 b 会有什么结果呢?
std::cout << wp.use_count()<<"\n";//有两个引用 但实际上应该是4个,因为A* a B* b还有两个
// 结果:2 证明这个引用的控制和 a b 没有关系。
// 那么有就是说明了,如果我们使用了智能指针,就不要在使用A* a A* b 这种用法了,
// 或者说用了,但是不要 delete,因为这个对象已经被智能制造管理了,我们就不要对他的生命周期有任何的干预了,由智能制指针负责就好了。
delete a;
//结果:可以删除但是会报异常
//删除一个对象后,指针的引用数量会有什么变化呢?
std::cout << wp.use_count() << "\n";
// 结果:因为前面报了异常,所以这个结果也就没法确认了。
std::cout << "Hello World!\n";
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门使用技巧:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件
3.实验结果
A fun
a addr:0000021C7D370B40 b addr:0000021C7D370B40
2