C++智能指针 unique_ptr

C++智能指针 unique_ptr

概念

unique_ptr“唯一”拥有其所指对象,同一时刻只能有一个unique_ptr指向给定对象(通过禁止拷贝语义、只有移动语义来实现)。

unique_ptr指针本身的生命周期:从unique_ptr指针创建时开始,直到离开作用域。离开作用域时,若其指向对象,则将其所指对象销毁(默认使用delete操作符,用户可指定其他操作)。

unique_ptr指针与其所指对象的关系:在智能指针生命周期内,可以改变智能指针所指对象,如创建智能指针时通过构造函数指定、通过reset方法重新指定、通过release方法释放所有权、通过移动语义转移所有权。

基本操作

#include <iostream>
#include <memory>
using namespace std;
int main() {
    unique_ptr<int> uptr;
    uptr.reset(new int(3));
    cout << *uptr << endl;
    int* ptr = uptr.release();
    // cout << *uptr << endl;
    // error. uptr = nullptr
    cout << *ptr << endl;
    uptr.reset(new int(4));
    unique_ptr<int> ano_uptr(new int(5));
    uptr.swap(ano_uptr);
    cout << *uptr << endl;  // *uptr = 5
    cout << *ano_uptr << endl; // *ano_uptr = 4
    delete ptr;
    return 0;
}

使用场景

1. 动态资源的异常保护

详情见前文资源管理对把分配资源放入容器中的讨论。

2. 返回函数内创建的资源

由于在函数中创建资源是非常容易导致内存泄露的。因为客户可能会忘记哪个指针指向了on the heap的资源。

unique_ptr<X> foo()  
{  
    unique_ptr<X> px(new X);  
    // do something 
    return px; //移动语义 
}  

3. 可放入容器中

弥补了auto_ptr不能放入容器中的问题。同时unique_ptr并无copy语义,只能用move转移语义。

#include <iostream>
#include <memory>
#include <vector>
using namespace std;
int main() {
    vector< unique_ptr<string> > vec_of_uptr;
    vec_of_uptr.push_back(unique_ptr<string>(new string("yan")));
    vec_of_uptr.push_back(unique_ptr<string>(new string("ze")));
    vec_of_uptr.push_back(unique_ptr<string>(new string("xin")));
    unique_ptr<string> new_one(new string("new"));
    vec_of_uptr.push_back(move(new_one));
    return 0;
}

4. 动态管理数组

    unique_ptr<int[]> array_ptr(new int [3]{1, 2, 3});
    array_ptr[0] = 2;

5. 自定义资源删除操作

unique_prt的部分源码。(使用了成员模板)

    template <class _Up, class _Ep>
        unique_ptr(unique_ptr<_Up, _Ep>&);

unique_ptr默认的资源删除操作是delete/delete[],若需要,可以进行自定义:在 资源管理 介绍shared_ptr时也有提及这部分内容。简单的说,就是我们析构资源不一定是delete,可能是要我们自定义的函数。

void end_connection(connection *p) { disconnect(*p); } //资源清理函数 
unique_ptr<connection, decltype(end_connection)*> //资源清理器的“类型” 
        p(&c, end_connection);// 传入函数名,会自动转换为函数指针 

6. auto_ptr与unique_ptr

在C++11环境下,auto_ptr被看做“遗留的”,他们有如下区别:

  • auto_ptr有拷贝语义,拷贝后源对象变得无效;unique_ptr则无拷贝语义,但提供了移动语义
  • auto_ptr不可作为容器元素,unique_ptr可以作为容器元素
  • auto_ptr不可指向动态数组(尽管不会报错,但不会表现出正确行为),unique_ptr可以指向动态数组

你可能感兴趣的:(C++智能指针 unique_ptr)