1. 几个基本成员函数的作用:
u.reset() 释放u指向的对象
u.reset(q) 如果提供了内置指针q,就令u指向这个对象
u.reset(nullptr) 将 u 置为空
u.release() u 放弃对指针的控制权,返回指针,并将 u 置为空
2. 一些规则:
- 某个时刻只能有一个unique_ptr 指向一个给定的对象。当它销毁时,它所指向的对象也会被销毁。
- 初始化 unique_ptr 只能采用直接初始化的方式 (explicit 关键字)
- 不支持复制构造与赋值操作
- 在创建或者是reset一个具有删除器的unique_ptr 时,必须提供删除器
- 不支持拷贝与赋值的规则有一个例外,那就是我们可以拷贝或者赋值一个将要被销毁的unique_ptr(右值引用) ,比如:
/* 从函数返回一个unique_ptr */
unique_ptr<int> clone(int p ){
return unique_ptr<int>(new int(p));
}
/* 返回一个局部对象的拷贝 */
unique_ptr<int> clone(int p ){
unique_ptr<int> ret(new int (p));
return ret ;
}
- noexcept :在C++11中,声明一个函数不可以抛出任何异常使用关键字noexcept.
3. unique_ptr使用场景
1、为动态申请的资源提供异常安全保证
2、返回函数内动态申请资源的所有权
3、在容器中保存指针
4、管理动态数组
5、作为auto_ptr的替代品
/*unique_ptr.h 文件 */
#ifndef _UNIQUE_PTR_H
#define __UNIQUE_H
class Delete {
public:
template<typename T>
void operator()(T *p) const {
delete p;
}
};
template<typename T,typename D = Delete >
class unique_ptr {
public:
explicit unique_ptr(T *pp = nullptr ,const D &dd= D() )
:un_ptr(pp),del(dd)
{
}
~unique_ptr() {
del(un_ptr);
}
/* 不支持拷贝与赋值 */
unique_ptr(const unique_ptr&) = delete ;
unique_ptr& operator=(const unique_ptr& ) = delete ;
/*可以拷贝或者赋值一个将要被销毁的 unique_ptr(右值引用)*/
unique_ptr( unique_ptr&& right_value):
un_ptr(right_value.un_ptr),del(std::move(right_value.del)) {
right_value.un_ptr = nullptr ;
}
unique_ptr& operator=( unique_ptr&& right_value ) noexcept {
if(this != &right_value ){
std::cout << "operator && right_value " << std::endl ;
del(*this);
un_ptr = right_value.un_ptr;
del = std::move(right_value.del);
right_value.un_ptr = nullptr ;
}
return *this ;
}
//u.release() u 放弃对指针的控制权,返回指针,并将 u 置为空
T* release(){
T *tmp = un_ptr ;
un_ptr = nullptr ;
return tmp ;
}
/*
u.reset() 释放u指向的对象
u.reset(q) 如果提供了内置指针q,就令u指向这个对象
u.reset(nullptr) 将 u 置为空
*/
void reset(){ del(un_ptr); }
void reset(T* q ){
if( un_ptr ){
del(un_ptr) ;
un_ptr = q ;
}
else
un_ptr = nullptr ;
}
void swap(unique_ptr &other ) noexcept {
using std::swap ;
swap( un_ptr,other.un_ptr );
swap(del,other.del) ;
}
T* get() { return un_ptr ; }
D& get_deleter(){ return del ; }
T& operator*() { return *un_ptr ; }
T* operator->() { return un_ptr ; }
private:
T *un_ptr = nullptr ;
D del ;
};
#endif
/* main.cpp 文件 */
#include <iostream>
#include <string>
//#include"shared_ptr.h"
#include "unique_ptr.h"
#include"DebugDelete.h"
#include <assert.h>
struct Foo {
Foo() { std::cout << "Foo()\n"; }
~Foo() { std::cout << "~Foo()\n"; }
Foo(const Foo&) { std::cout << "Foo copy ctor\n"; }
Foo(Foo&&) { std::cout << "Foo move ctor\n"; }
};
struct Fooo {
Fooo(int n = 0) noexcept : bar(n) { std::cout << "Fooo: constructor, bar = " << bar << '\n'; }
~Fooo() { std::cout << "Fooo: destructor, bar = " << bar << '\n'; }
int GetBar() const noexcept { return bar; }
private:
int bar;
};
struct D {
void bar() { std::cout << "Call deleter D::bar()...\n"; }
void operator()(Foo* p) const
{
std::cout << "Call delete from function object...\n";
delete p;
}
};
using namespace std ;
int main()
{
unique_ptr<string> p1(new string("Shengxi-Liu"));
cout << *p1 << endl ;
{
std::cout << "======================\nunique_ptr constructor:\n";
unique_ptr<Foo> up1;
unique_ptr<Foo> up1b(nullptr);
unique_ptr<Foo> up2(new Foo);
DebugDelete d;
unique_ptr<Foo, DebugDelete> up3(new Foo, d);
unique_ptr<Foo, DebugDelete&> up3b(new Foo, d);
unique_ptr<Foo, DebugDelete> up4(new Foo, DebugDelete());
unique_ptr<Foo> up5b(std::move(up2));
unique_ptr<Foo, DebugDelete> up6b(std::move(up3));
unique_ptr<Foo> up7 = std::move(up5b);
Foo* fp = up7.release();
assert(up7.get() == nullptr);
delete fp;
up6b.reset(new Foo());
up6b.reset(nullptr);
unique_ptr<Fooo> up71(new Fooo(1));
unique_ptr<Fooo> up72(new Fooo(2));
up71.swap(up72);
std::cout << "up71->val:" << up71->GetBar() << std::endl;
std::cout << "up72->val:" << (up72.get())->GetBar() << std::endl;
unique_ptr<Foo, D> up8(new Foo(), D());
D& del = up8.get_deleter();
del.bar();
}
}