原因:介绍一下unique_ptr的使用说明
概况:
介绍:unique_ptr包含在memory头文件中,通过一个指针占用和管理一块内存。并在unique_ptr的作用域退出时释放改内存。
主要定义方式如下两种:可以看出第一种释放函数为自带的delete操作符,而第二种情况为我们自己定义的释放函数。
template<class T, class Deleter = std::default_delete<t>>class unique_ptr;
template<class T,class Deleter>class unique_ptr<t[],deleter>;
具体调用如下:通过function关键字定义一个函数模板.并传递实现的delete_函数指针。
void delete_(cuniqt2 *i)
{
printf("delete_\n");
}
{
std::unique_ptr<cuniqt2, std::function<void(cuniqt2 *i)>>w(new(cuniqt2), delete_);
}
具体的delete方法参数通过源码的析构函数可以看出,释放函数只有一个参数,改参数就是定义unique_ptr的模板类型如下:
~unique_ptr() _NOEXCEPT
{ // destroy the object
if (get() != pointer())
this->get_deleter()(get());
}
通过源码可以看出unique_ptr没有拷贝构找函数和赋值函数如下:
unique_ptr(const _Myt&) = delete;
_Myt& operator=(const _Myt&) = delete;
所以具体的赋值如下:此时就使用到了move关键字,通过该关键字实现对象的转换,
std::unique_prt<a>up1(new a(5));
std::unique_ptr<a>up2(up1);//错误,不支持拷贝构造函数
std::unique_ptr<a>up2;
up2 = up1;//错误,不支持赋值函数
std::unique_prt<a>up2(std::move(up1))//正确,移动构造函数
std::unique_ptr<a>up2=(std::move(up1))//
通过unique_ptr实现基类和派生类的转换,调用如下:通过调用可以看出只有当基类析构函数为虚函数时才不会造成内存泄露的问题。如果使用shared_ptr则不会有这个问题
class cuniqt {
public:
virtual void test() { printf("in cuniqt\n"); };
virtual ~cuniqt(){ printf("cuniqt\n"); };
};
class cuniqt2 :public cuniqt
{
public:
void test() { printf("in cuniqt2\n"); };
~cuniqt2() { printf("cuniqt2\n"); };
};
{
std::unique_ptr<cuniqt2>q(new(cuniqt2));
q->test();//输出in cuniqt2
std::unique_ptr<cuniqt>p(std::move(q));
p->test();//输出in cuniqt2
}//如果基类析构函数不是virtual,则最终调用析构函数为为基类,而如果基类析构函数为virtual则最终调用析构函数顺序为派生类,基类。
有关unique_ptr的方法介绍:
release:返回一个指向被管理对象的指针,并释放所有权
std::unique_ptr<int>q(new(int));
int *p = q.release();此时q的对象被释放.
reset:替换被管理对象
std::unique_ptr<int>q(new(int));
q.reset(new(int));首先释放原有的对象,然后赋值新的对象
swap:交换被管理对象
std::unique_ptr<int>q(new(int));
std::unique_ptr<int>p(new(int));
q.swap(p);对象交换
get:返回指向被管理对象的指针
std::unique_ptr<int>q(new(int));
int *p = q.get();此时p和q指向相同位置。且q不会被释放.
get_delete:返回用于析构的管理器