目录
不支持操作:该指针不支持拷贝和赋值操作;所以不能拷贝到容器里
unique_ptr
概述
独占式指针(专属所有权),同一时刻,只能有一个unique_ptr指向这个对象;当指针销毁,指向的对象也销毁;因此该指针不支持拷贝和赋值操作,也不存在引用计数。
涉及程序
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
class A
{
public:
A()
{
cout << "A" << endl;
}
A(int num) : m_num(num)
{
cout << "A int" << endl;
}
A(const A &&other) : m_num(other.m_num)
{
cout << "A move int" << endl;
}
~A()
{
cout << "~A" << endl;
}
public:
int m_num;
};
void mydelete(A *p)
{
delete[] p;
}
int main(int argc, char const *argv[])
{
#if 0
unique_ptr<int> p(new int(5)); //可以指定删除器
unique_ptr<int> p2 = make_unique<int>(6); //不可用指定删除器
// unique_ptr<int>p2 = p;
//指定删除器
// unique_ptr<A[]>pa(new A[3]);
using p_delete = void (*)(A * p);
unique_ptr<A, p_delete> pa(new A[3], mydelete);
unique_ptr<A>ptr(new A());
vector<unique_ptr<A>>vp;
// vp.push_back(pa);
// vp.push_back(ptr);
cout << sizeof(pa) <<endl;
cout << sizeof(ptr) <<endl;
// shared_ptr<A> pa(new A[3], mydelete);
// shared_ptr<A> ptr(new A(5));
// vector<shared_ptr<A>>vp;
// vp.push_back(pa);
// vp.push_back(ptr);
//release():放弃智能指针的控制权,将该指针置为nullptr,返回的是裸指针
unique_ptr<int>pi(new int(5));
int *temp = pi.release();
if(pi = nullptr)
{
cout <<"pi is nullptr"<<endl;
}
cout << *temp<<endl;
//reset() reset(参数)
unique_ptr<int>p2(new int(5));
p2.reset();
p2.reset(new int(6));
cout << *p2<<endl;
#endif
//移动语义std::move()
unique_ptr<A> ptr(new A(5));
unique_ptr<A> &&rptr = std::move(ptr);
cout << ptr->m_num <<endl;
cout << rptr->m_num <<endl;
return 0;
}
初始化
手动初始化
unique_ptr p;或unique p(new int(5))
std::make_unique函数(C++14)
注:生成的指针不支持指定删除器语法
unique_ptr常规操作
不支持操作:该指针不支持拷贝和赋值操作;所以不能拷贝到容器里
不支持拷贝:
不支持赋值:
无法拷贝到容器
移动语义std::move();
使用右值引用可以进行赋值
release();
放弃对指针的控制权,将该指针置nullptr,返回裸指针;
注:返回的裸指针手动释放(防止内存泄漏)或者可以初始化另一个指针
reset();
- reset()无参使用:若该智能指针是独占某个对象,则释放该对象,并将智能指针置nullptr;
- reset()代参使用:若该智能指针是独占某个对象,则释放该对象,并将该指针指向新对象;
实例:p.reset();p.reset(new int());
*解应用
获得智能指针指向的对象,并对其操作;
get();
考虑到有些函数参数是裸指针并不是智能指针,所以需要将智能指针转化为裸指针;
获得智能指针中保存的指针(裸指针);
注:获得裸指针要小心使用,因为智能指针一旦释放,裸指针也就失效;
指定删除器
语法:unique_ptr 智能指针变量名
以下图为例,当指针指向一段连续的数组空间时,会产生内存泄漏
一般的解决办法是指定数组(加“[ ]”)
自定义删除函数
unique_ptr的删除器需要我们指定删除器的类型,当我们像shared_ptr一样直接传入删除器就会产生报错,如下图所示:
指定删除器类型操作如下图所示,运行结果正常
注:unique_ptr的删除器类型可以任意定义,而shared_ptr的删除器类型必须是void类型
unique_ptr和shared_ptr指定删除器时的区别
区别1:unique_ptr在使用时必须要指定删除器的类型,而shared_ptr不需要指定
区别2:
- 同类型的shared_ptr拥有不同的删除器,那么这些shared_ptr仍然是相同类型的
根据容器的特性,类型相同的变量可以存放在同一个容器中,我们使用vector容器成功验证了shared_ptr,如下图所示
- 而指定不同删除器会导致不同类型的unique_ptr,因为unique_ptr的尺寸会发生变化
通过输出指针的大小,就可以发现不同删除器的unique_ptr的大小都不一样
但不能通过push_back插入到容器中的操作来验证,因为push_back是通过拷贝的操作将变量添加到容器中,而unique_ptr不支持拷贝操作
unique_ptr尺寸
unique_ptr的尺寸和裸指针一样大,但是指定自定义删除函数会影响尺寸大小;