【C++智能指针篇】详解unique_ptr,类模板,使用场景和部分功能

文章目录

  • unique_ptr的特点:
    • 无法进行拷贝构造和赋值操作的原因:
    • 可以使用移动赋值和移动构造
  • 类模板:
    • 泛化版本:
    • 部分特化:
    • 完全特化:
  • unique_ptr一般的用法:
      • 1.1 创建和删除一个对象:
      • 1.2 创建和删除一组对象:
    • 3. 为什么unique可以实现删除一组和一个对象。
    • 4. 自己实现删除功能:
      • 4.1 使用自己设计delete
    • 5. unique_ptr使用场景
      • 5.1 为动态申请的资源提供安全保证。
      • 5.2 返回函数内存申请资源的所有权
      • 5.3 在容器中保存指针
      • 5.4 动态管理数组

unique_ptr: 拥有独有对象所有权语义的智能指针。

unique_ptr的特点:

unique_ptr 是一种定义在中的智能指针。
1:unique_ptr 对象不能进行赋值操作和移动操作。
2:unique是独特的,唯一的意思,因此表示它独占一个对象。
3:unique_ptr和share_ptr类型有很大的不同,share_ptr允许多个指针指向同一个对象,而unique_ptr在某一时刻只能有一个指针指向该对象。两个unique不能指向同一个对象。
4.unique_ptr对象中保存指向某个对象的指针,当它本身被删除或者离开其作用域就会被自动释放其指向对选哪个所占有的资源。

无法进行拷贝构造和赋值操作的原因:

  //将拷贝构造函数删除
    my_unique_ptr(const my_unique_ptr&) = delete;
   //将赋值语句删除
   my_unique_ptr &operator=(const my_unique_ptr&) = delete
int main()
{
    std::unique_ptr<Object> pobja(new Object(10));
   //std::unique_ptr pobjc(pobja);//不能进行赋值。使2个指针指向指向同一个对象
    std::unique_ptr<Object> pobjb;
   //pobjc = pobja;//赋值语句被删掉了
   // pobjc = fun();//调用赋值语句,也不行
  
}

可以使用移动赋值和移动构造

std::unique_ptr<Object> pobjc(std::move(pobja));

int main()
{
    std::unique_ptr<Object> pobja(new Object(10));
    std::unique_ptr<Object> pobjc(std::move(pobja));
    pobjb = std::move(pobja);
    //底层 std::(unique_ptr&&)(pobja);将pobja对象强转为右值
}

【C++智能指针篇】详解unique_ptr,类模板,使用场景和部分功能_第1张图片
实现移动构造

 my_unique_ptr(my_unique_ptr &&p)
    {
        _ptr = p._Ptr;
        p._Ptr = NULL;
    }

实现移动赋值

  my_unique_ptr& operator=(my_unique_ptr&& p)
    {
        if (this == *p)  retun* this;
            delete _Ptr;
            _Ptr = p._Ptr
            p.Ptr = NULL;
           return *this;
    }

类模板:

泛化版本:

template<class T,class D>
class my_unique_ptr
{
    my_unique_ptr() { cout << "T,D" << endl; }
};

部分特化:

template<class T, class D>
class my_unique_ptr<T*,D*>
{
    my_unique_ptr() { cout << "T*,D*" << endl; }
};
template<class T, class D>
class my_unique_ptr<const T*,  const D*>
{
    my_unique_ptr() { cout << "const T*,const D*" << endl; }
};

完全特化:

template<>
class my_unique_ptr<const char*, const char*>
{
    my_unique_ptr() { cout << "const char*, const char*" << endl; }
};
int main()
{
    my_unique_ptr<int, int>a;
    my_unique_ptr<int*, int*> b;
    my_unique_ptr<const int*, const int*> c;
    my_unique_ptr<const char*, const char*> d;
}

unique_ptr一般的用法:

1.1 创建和删除一个对象:

std::unique_ptr<Object> obja(new Object(10));//执行的是自己自带的delete

1.2 创建和删除一组对象:

std::unique_ptr<Object[]> objb(new Object[10]);//执行的是自己自带的delete[]

3. 为什么unique可以实现删除一组和一个对象。

因为它定义了两个类模板,一个泛化版本和一个部分特化版本,如下:

template<class T,class D>
class my_unique_ptr
{
public:
    my_unique_ptr() { cout << "T,D" << endl; }
};
template<class T, class D>
class my_unique_ptr<T[],D>
{
public:
    my_unique_ptr() { cout << "T[],D" << endl; }
};

4. 自己实现删除功能:

struct delete_Object
{
    void operator()(Object* op)
    {
        if (op == NULL) return;
        delete op;
    }
};
struct delete_arr_Object
{
    void operator()(Object* op)
    {
        if (op == NULL) return;
        delete[] op;
    }
};

4.1 使用自己设计delete

int main()
{
std::unique_ptr<Object, delete_Object> objc(new Object(10));//执行的是设计的delete
    std::unique_ptr<Object[], delete_arr_Object> objd(new Object[10]);
}

从这个方面我们就可以看出指针指针带来巨大的灵活性,我们还可以用它来操作文件:
比如:

int main()
{           
    std::unique_ptr<FILE, delete_file> objd(fopen("tulun.txt","w"));
}
struct delete_file
{
    void operator()(FILE *fp)
    {
        if (fp == NULL) return;
        fclose(fp);
    }
};
class my_unique_ptr
{
private:
    T* _Ptr;
public:
    my_unique_ptr() { cout << "T,D" << endl; }
    operator bool()()const{ return _Ptr != NULL; }
};
int main()
{
 if (!pfile)
    {
        cout << "file open err" << endl;
    }
    }

5. unique_ptr使用场景

5.1 为动态申请的资源提供安全保证。

如下:传统写法,当接下来的代码由于抛出异常或提前退出,就会没有执行delete操作。

void func()
{
   int *p = new int(5);
   //....提前退出,抛出异常
   delete p ;
}

解决办法:使用unique_ptr来动态管理内存,直接unique_ptr创建成功,其析构函数就会被调用,确保动态资源释放。

void func()
{
   std::unique_ptr<int> p(new int(5));
}

5.2 返回函数内存申请资源的所有权

unique_ptr<int> func(int x)
{
    unique_ptr<int> p(new int(x));//自动将pdelete
    return p;
}
int main()
{
    int a = 5;
    unique_ptr<int> ret = func(a);//自动将ret,delete
    cout << *ret << endl;
    //函数结束自动释放new的资源
}

5.3 在容器中保存指针

int main()
{
    vector<unique_ptr<int> >vec;
    unique_ptr<int> p(new int(5));
    vec.push_back(std::move(p));//使用移动构造,移动赋值
}

5.4 动态管理数组

int main()
{
    unique_ptr<int[]> p(new int[5]{ 1,2,3,4,5 });
    p[0] = 0;
}

你可能感兴趣的:(C++深入学习,c++,开发语言)