智能指针
c++中不像java自带垃圾回收机制,必须释放掉分配的内存,否则机会造成内存泄漏。因此c++11加入了智能指针。智能指针是存储指向动态分配(堆)对象指针的类,用于生存期的控制,能够确保在离开指针所在作用域时,自动的销毁分配的对象,防止内存泄漏。智能指针的核心实现技术是引用技术,每使用它一次内部引用计数+1,每析构一次内部引用技术-1,减为0时,删除原始指针指向的堆区内存,使用智能指针需要引用头文件<memory>.
std::shared_ptr:共享的智能指针
std::unique_ptr:独占的智能指针
std::weak_ptr:弱引用的智能指针,它不共享指针,不能操作资源,是用来监视shared_ptr的,解决循环引用问题。
share_ptr(共享智能指针)
初始化:
共智能指针是指多个智能指针可以同时管理同一块有效的内存,共享智能指针share_ptr是一个模板类,如果进行初始化有三种方式如下:
通过构造函数初始化
std::make_shared辅助函数
reset方法
共享智能指针对象初始化完毕之后就指向了要管理的那块堆区内存,如果想要查看当前有多少个智能指针同时管理着这块内存可以使用共享指针提供的一个成员函数use_count.
构造函数初始化
构造函数初始化
//构造函数
shared_ptr<int> ptr1(new int(520));
cout<<"ptr1 管理的内存引用技术:"<<ptr1.use_count()<<endl;
//拷贝构造函数
shared_ptr<int> ptr2(ptr1);
cout<<"ptr2 管理的内存引用技术:"<<ptr2.use_count()<<endl;
shared_ptr<int>ptr3 = ptr1;
cout<<"ptr3管理的内存引用技术:"<<ptr3.use_count()<<endl;
//移动构造函数
shared_ptr<int> ptr4(std::move(ptr1));
cout<<"ptr4管理的内存引用技术:"<<ptr4.use_count()<<endl;
std::shared_ptr<int> ptr5 = std::move(ptr2);
cout<<"ptr5管理的内存引用技术:"<<ptr5.use_count()<<endl;
打印结果为:1 1 0 0
如果智能指针被初始化了一块有效内存,那么这块内存的引用技术+1,如果智能指针没有被初始化或者被初始化为nullptr空指针,引用计数为0,另外,不要使用一个原始指针初始化多个shared_ptr。
拷贝和移动构造函数初始化
当一个智能指针被初始化后,就可以通过这个智能指针初始化其他新的对象。在创建新对象的时候,对应的拷贝构造函数或者移动构造函数就被调用了
//构造函数
shared_ptr<int> ptr1(new int(520));
cout<<"ptr1管理的内存引用计数:"<<ptr1.use_count()<<endl;
//拷贝构造函数
shared_ptr<int> ptr2(ptr1);
cout<<"ptr2管理的内存引用计数:"<<ptr2.use_cont()<<endl;
shared_ptr<int> ptr3 = ptr1;
cout<<"ptr3管理的内存引用计数:"<<ptr3.use_count()<<endl;
//移动构造函数
shared_ptr<int> ptr4(std::move(ptr1));
cout<<"pptr4管理的内存引用计数:"<<ptr4.use_count()<<endl;
std::shared_ptr<int> ptr5 = std::move(ptr2);
cout<<"ptr5管理的内存引用计数:"<<ptr5.use_count()<<endl;
打印结果: 1 2 3 3 3
如果使用拷贝的方式初始化共享智能指针,这两个对象会同时管理同一块内存,堆内存对应的引用技术也会增加。如果使用移动构造的方式初始化智能指针对象,只是转让了内存的所有权,管理内存的对象不会增加,因此内存引用计数不会增加。
std::make_shared 初始化
通过c++11提供的std::make_shared()就可以完成内存对象的创建并将其初始化给智能指针
#include<iostream>
#include<string>
#include<memory>
using namespace std;
class Test
{
public:
Test()
{
cout<<"无参构造函数"<<endl;
}
Test(int x)
{
cout<<"int 类型构造函数"<<x<<endl;
}
Test(string str)
{
cout<<"string类型的构造函数"<<str<<endl;
}
~Test()
{
cout<<"析构函数"<<endl;
}
};
int main()
{
//使用智能指针管理一快int型的堆内存,内部引用计数为1
shared_ptr<int> ptr1 = make_shared<int>(520);
cout<<"ptr1管理的内存引用计数:"<<ptr.use_count()<<endl;
shared_ptr<Test> ptr2 = make_shared<Test>();
cout<<"ptr2管理的内存引用计数:"<<ptr2.use_cont()<<endl;
shared_ptr<Test> ptr3 = make_shared<Test>(520);
cout<<"ptr3管理的内存引用计数:"<<ptr3.use_count()<<endl;
shared_ptr<Test> ptr3 = make_shared<Test>(QQQ);
cout<<"ptr4管理的内存引用计数:"<<ptr4.use_count()<<endl;
}
#include<iostream>
#include<string>
#include<memory>
using namespace std;
int main()
{
//使用智能指针管理一块int型的堆内存,内部引用计数为1
shared_ptr<int> ptr1 = make_shared<int>(520);
shared_ptr<int> ptr2 = ptr1;
shared_ptr<int> ptr3 = ptr1;
shared_ptr<int> ptr4 = ptr1;
cout<<"ptr1管理的内存引用计数:"<<ptr1.use_count()<<endl;
cout<<"ptr2管理的内存引用计数:"<<ptr2.use_count()<<endl;
cout<<"ptr3管理的内存引用计数:"<<ptr3.use_count()<<endl;
cout<<"ptr4管理的内存引用计数:"<<ptr4.use_count()<<endl;
ptr4.reset();
cout<<"ptr1管理的内存引用计数:"<<ptr1.use_count()<<endl;
cout<<"ptr2管理的内存引用计数:"<<ptr2.use_count()<<endl;
cout<<"ptr3管理的内存引用计数:"<<ptr3.use_count()<<endl;
cout<<"ptr4管理的内存引用计数:"<<ptr4.use_count()<<endl;
shared_ptr<int> ptr5;
ptr5.reset(new int(250));
cout<<"ptr5管理的内存引用计数:"<<ptr5.use_count()<<endl;
return 0;
}
对于一个未初始化的共享智能指针,可以通过reset方法来初始化,当智能指针中有值的时候,调用reset会使引用计数-1.
获取原始指针
get()函数
int main()
{
shared_ptr<int> p(new int);
*p = 100;
cout<<*p.get()<<""<<*p<<endl;
return 0;
}
100 100