智能指针分为:auto_ptr、shared_ptr、weak_ptr、unique_ptr。
智能指针主要作用:
1、防止忘记调用delete释放内存;
2、管理在堆上分配的内存,它将普通的指针封装为一个栈对象,实质是一个对象。当栈对象的生存周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄漏。
-
shared_ptr
-
1、定义
shared_ptr多个指针指向相同的对象。shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。每使用他一次,内部的引用计数加1,每析构一次,内部的引用计数减1,减为0时,自动删除所指向的堆内存。shared_ptr内部的引用计数是线程安全的,但是对象的读取需要加锁;
-
2、方法
成员函数 作用 use_count() 查看资源的所有者个数 new() 构造,还可以通过传入auto_ptr, unique_ptr,weak_ptr来构造 release() 当前指针会释放资源所有权,计数减一。当计数等于0时,资源会被释放 unique() 返回是否是独占所有权( use_count 为 1) swap() 交换两个 shared_ptr 对象(即交换所拥有的对象) reset () 放弃内部对象的所有权或拥有对象的变更, 会引起原有对象的引用计数的减少 get 返回内部对象(指针), 由于已经重载了()方法, 因此和直接使用对象是一样 -
3、例子
string *s1 = new string("s1"); shared_ptr<string> ps1(s1); shared_ptr<string> ps2; ps2 = ps1; cout << ps1.use_count()<<endl; //2 cout<<ps2.use_count()<<endl; //2 cout << ps1.unique()<<endl; //0 string *s3 = new string("s3"); shared_ptr<string> ps3(s3); cout << (ps1.get()) << endl; //033AEB48 cout << ps3.get() << endl; //033B2C50 swap(ps1, ps3); //交换所拥有的对象 cout << (ps1.get())<<endl; //033B2C50 cout << ps3.get() << endl; //033AEB48 cout << ps1.use_count()<<endl; //1 cout << ps2.use_count() << endl; //2 ps2 = ps1; cout << ps1.use_count()<<endl; //2 cout << ps2.use_count() << endl; //2 ps1.reset(); //放弃ps1的拥有权,引用计数的减少 cout << ps1.use_count()<<endl; //0 cout << ps2.use_count()<<endl; //1
-
-
weak_ptr
-
1、定义
weak_ptr是用来解决shared_ptr相互引用时的死锁问题,可以从一个 shared_ptr 或另一个 weak_ptr 对象构造, 它的构造和析构不会引起引用记数的增加或减少,观测资源的使用情况
-
2、创建
1、可以创建一个空 weak_ptr 指针 std::weak_ptr<int> wp1; 2、凭借已有的 weak_ptr 指针,可以创建一个新的 weak_ptr 指针 std::weak_ptr<int> wp2 (wp1); 3、weak_ptr 指针更常用于指向某一 shared_ptr 指针拥有的堆内存,因为在构建 weak_ptr 指针对象时,可以利用已有的 shared_ptr 指针为其初始化 std::shared_ptr<int> sp (new int); std::weak_ptr<int> wp3 (sp); wp3 指针和 sp 指针有相同的指针。再次强调,weak_ptr 类型指针不会导致堆内存空间的引用计数增加或减少
-
2、成员函数
成员函数 作用 use_count() 观测资源的引用计数 expired() 表示被观测的资源(也就是shared_ptr的管理的资源)已经不复存在,等价于use_count()==0 lock() 从被观测的shared_ptr获得一个可用的shared_ptr对象,expired()==true的时候,lock()函数将返回一个存储空指针的shared_ptr operator=() 重载 = 赋值运算符,是的 weak_ptr 指针可以直接被 weak_ptr 或者 shared_ptr 类型指针赋值。 swap(x) 其中 x 表示一个同类型的 weak_ptr 类型指针,该函数可以互换 2 个同类型 weak_ptr 指针的内容 reset() 将当前 weak_ptr 指针置为空指针 -
3、例子
#include <iostream> #include <memory> using namespace std; int main() { std::shared_ptr<int> sp1(new int(10)); std::shared_ptr<int> sp2(sp1); std::weak_ptr<int> wp(sp2); 输出和 wp 同指向的 shared_ptr 类型指针的数量 cout << wp.use_count() << endl; // 2 释放 sp2 sp2.reset(); cout << wp.use_count() << endl; // 1 借助 lock() 函数,返回一个和 wp 同指向的 shared_ptr 类型指针,获取其存储的数据 cout << *(wp.lock()) << endl; // 10 return 0; }
-
-
unique_ptr
-
1、定义
一个对象和其对应的资源同一时间只被一个pointer拥有。一旦拥有者被销毁或者变成empty或者开始拥有另一个对象,先前拥有的那个对象就会被销毁,其任何相应资源亦会被释放。
unique_ptr具有->和*运算符重载符,因此它可以像普通指针一样使用。 -
2、创建
1、可以用原始指针当实参传给构造函数 unique_ptr<int> up1(new int(1)); 2、make_unique函数 unique_ptr<string> up2 = make_unique<string>("hello"); 3、 int* p = new int; unique_ptr<int> up3(p);//ok unique_ptr<int> up4(up3);//error,不可以对unique_ptr执行copy或者assign操作,只能move unique_ptr<int> up5 = up3; //error unique_ptr<int> up6(move(up3));//ok
-
3、成员函数
-
1)release()
放弃对指针的控制权,即切断了智能指针和其所指向的对象之间的联系。返回裸指针,将该智能指针置空。
返回的这个裸指针我们可以手动delete来释放,也可以用来初始化另外一个智能指针,或者给另外一个智能指针赋值。unique_ptr<string> ps1(new string("I Love China!")); unique_ptr<string> ps2(ps1.release()); // release后,ps1 == nullptr // 错误: ps2.release(); // 会导致内存泄漏 unique_ptr<string> ps1(new string("I Love China!")); unique_ptr<string> ps2(ps1.release()); // release后,ps1 == nullptr // 正确: string* p = ps2.release(); // 可以简写为auto p = p2.release(); delete p; // 手动delete释放
-
2) move()
unique_ptr<string> ps1(new string("hello!")); unique_ptr<string> ps2 = move(ps1); // 移动后,ps1为空,ps2指向原来ps1所指
-
3) reset()
reset() 不带参数:释放智能指针所指向的对象,并将智能指针置空。
unique_ptr<string> ps1(new string("hello")); ps1.reset(); // reset后,ps1 == nullptr
reset() 带参数:释放智能指针所指向的对象,并让该智能指针指向新对象。
unique_ptr<string> ps1(new string("I Love China1!")); unique_ptr<string> ps2(new string("I Love China2!")); ps1.reset(ps2.release()); // release后,ps2被置空;reset后,释放ps1指向的对象内存,让ps1指向ps2所指向的内存
-
4) nullptr
释放智能指针所指向的对象,并将智能指针置空。
unique_ptr<string> ps1(new string("hello")); ps1 = nullptr; // 释放ps1所指向的对象,并将ps1置空
-
5) get()
返回智能指针中保存的裸指针
ps是一个智能指针,p是一个普通指针:
p = ps.get(); 后,ps并非被释放,也就相当于指针p和智能指针ps共同管理一个对象,所以就*p做的一切,都会反应到bar指向的对象上。 -
6) swap()
unique_ptr<string> ps1(new string("hello!")); unique_ptr<string> ps2(new string("world")); ps1.swap(ps2);
-
-
4、例子
#include <iostream> #include <memory> using namespace std; struct Task { int mId; Task(int id) :mId(id) { cout << "Task::Constructor" << endl; } ~Task() { cout << "Task::Destructor" << endl; } }; int main() { 通过原始指针创建 unique_ptr 实例 shared_ptr<Task> taskPtr(new Task(23)); int id = taskPtr->mId; 调用其lock函数来获得shared_ptr示例,进而访问原始对象。 weak_ptr<Task> weak1 = taskPtr; int id = weak1.lock()->mId; unique_ptr<Task> taskPtr(new Task(23)); int id = taskPtr->mId; cout << id << endl; return 0; }
-