栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

C++智能指针之unique

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++智能指针之unique

文章目录
  • C++智能指针之unique_ptr
    • unique_ptr篇
      • 简介
      • 成员函数
        • 构造函数
        • 析构函数
        • get
        • get_deleter
        • release
        • reset
        • swap
        • operator=
        • operator bool
      • 练习

C++智能指针之unique_ptr unique_ptr篇 简介

unique_ptr是一种定义在 中的智能指针,管理指针的存储,提供智能资源回收,并且与内置指针相比几乎没有开销(取决于使用的删除器)。它持有对对象的独有权,即两个unique_ptr不能指向一个对象,不能进行复制操作只能进行移动操作,离开作用域后自动删除指向的对象,或者显示调用 unique_ptr::reset。

成员函数 构造函数
constexpr unique_ptr() noexcept; // 默认构造函数1

std::unique_ptr u1; 
constexpr unique_ptr (nullptr_t) noexcept : unique_ptr() {}  // 默认构造函数2:传入空指针

std::unique_ptr u2 (nullptr);
explicit unique_ptr (pointer p) noexcept; // 传入其它指针

std::unique_ptr u3 (new int);
unique_ptr (pointer p,
    typename conditional::value,D,const D&> del) noexcept; // 传入指针和左值删除器

std::default_delete d;
std::unique_ptr u4 (new int, d);
unique_ptr (pointer p,typename remove_reference::type&& del) noexcept; // 传入指针和右值删除器

std::unique_ptr u5 (new int, std::default_delete());
unique_ptr (unique_ptr&& x) noexcept; // 调用move构造
std::unique_ptr u6 (std::move(u5));
template 
    unique_ptr (unique_ptr&& x) noexcept; // 调用move右值构造
std::unique_ptr u7 (std::move(u6));// u6->nullptr u7-> u6
template 
  unique_ptr (auto_ptr&& x) noexcept; // 通过移动 auto_ptr 构造
std::unique_ptr u8 (std::auto_ptr(new int))
unique_ptr (const unique_ptr&) = delete; // 拷贝构造

int *p = new int;
*p = 10;
std::unique_ptr u9 (p);
析构函数

如果对象是空(nullptr)则析构无效:

// ~unique_ptr();
// unique_ptr destructor example
#include 
#include 

int main () {
  auto deleter = [](int*p){
    delete p;
    std::cout << "[deleter called]n";
  };

  std::unique_ptr foo (new int,deleter);

  std::cout << "foo " << (foo?"is not":"is") << " emptyn";

  return 0;                        // [deleter called]
}
get

返回存储的指针。

pointer get() const noexcept;
#include 
#include 
int main()
{
  std::unique_ptr foo(new int);
  int *p = nullptr;
  p = foo.get();
  *p = 10;  

  std::cout << foo.get() << ":" << *foo << "n";
  std::cout << p << ":" << *p << "n";
  return 0;
}


get_deleter

返回对象存储的删除器。

      deleter_type& get_deleter() noexcept;
const deleter_type& get_deleter() const noexcept;
#include 
#include 

class myDeleter {
    int m_count;
public:
    myDeleter() :m_count(0){}
    template 
    void operator()(T* p) { // 重载操作符()
        if (p)
        {
            delete p;
            p = nullptr;
            std::cout << "deleter #" << ++m_count << 'n';
        }
    }
};

int main()
{
    {
        myDeleter del;

        std::unique_ptr one(new int, del); // 值
        std::unique_ptr two(new int, one.get_deleter()); // 值
        std::unique_ptr three(new int, one.get_deleter()); // 引用
        std::unique_ptr four(new int, del); // 值
        
        *one = 69;
        std::cout << one.get() << ":" << *one << "n";
        one.reset(); // count = 1

        *two = 96;
        std::cout << two.get() << ":" << *two << "n";
        two.reset(); // count = 1

        *three = 36;
        std::cout << three.get() << ":" << *three << "n";
        three.reset(); // count = 2

        *four = 63;
        std::cout << four.get() << ":" << *four << "n";
        four.reset(); // count = 1
    }

    std::cin.get();
    return 0;
}


release

释放对象存储的指针和对象所有权,并返回该指针。

pointer release() noexcept;
#include 
#include 
int main()
{
    std::unique_ptr foo(new int);
    int* p = foo.release();
    *p = 10;
    std::cout << foo.get() << "n";
    std::cout << p << ":" << *p << "n";
    delete p; // 注意:foo对象释放所有权后不再自动释放.
    return 0;
}


reset

如果p是空,销毁该对象管理的内存;

如果p不是空,销毁该对象管理的内存,并且该对象重新获取p的所有权;

void reset (pointer p = pointer()) noexcept;
#include 
#include 

int main()
{

    std::unique_ptr foo(new int);
    *foo = 10;
    {
        std::cout << "before foo calls reset:" << foo.get() << " : " << *foo << "n"; // 有效地址
        foo.reset(); //删除该指针管理的对象
        std::cout << "after foo calls reset:" << foo.get() << "n"; // 无效地址
        foo.reset(new int); //获取新的指针
        *foo = 11;
        std::cout << "before foo calls reset(p):" << foo.get() << ":" << *foo << "n"; // 有效地址
    }

    std::cin.get();
    return 0;
}


swap

交互俩个对象的所有权(包括deleter)

void swap (unique_ptr& x) noexcept;
#include 
#include 

int main()
{
    {
        std::unique_ptr foo(new int);
        std::unique_ptr bar(new int);
        *foo = 66;
        *bar = 99;
        std::cout << "before foo calls swap:" << foo.get() << " : " << *foo << "n";
        std::cout << "before bar calls swap:" << bar.get() << " : " << *bar << "n";
         foo.swap(bar);
         std::cout << "after foo calls swap:" << foo.get() << " : " << *foo << "n";
         std::cout << "after bar calls swap:" << bar.get() << " : " << *bar << "n";
    }
    std::cin.get();
    return 0;
}


operator=

获取对象的所有权和删除器(右值将被析构,所有权都转移,就像调用reset()方法一样)。

unique_ptr& operator= (unique_ptr&& x) noexcept; // 移动赋值
unique_ptr& operator= (nullptr_t) noexcept; // 赋值nullptr
template 
  unique_ptr& operator= (unique_ptr&& x) noexcept; // 类型转换赋值
unique_ptr& operator= (const unique_ptr&) = delete; // 拷贝赋值
#include 
#include 

int main()
{
    {
        std::unique_ptr foo;
        std::unique_ptr boo(nullptr); //  赋值nullptr

        foo = std::unique_ptr(new int(96)); // 类型转换赋值
        std::cout << "[foo]" << foo.get() << ':' << *foo << 'n';
        
        boo = std::move(foo); // 移动赋值
        std::cout << "[boo]"  << boo.get() << ':' << *boo << 'n';
    }

    std::cin.get();
    return 0;
}


operator bool

检测管理对象的指针是否为空(get()!=nullptr)。

explicit operator bool() const noexcept;
#include 
#include 

int main()
{
    {
        std::unique_ptr foo(new int);
        std::unique_ptr bar;     
        std::cout << "foo is " << (foo ? "not empty!n" : "emptyn");
        std::cout << "bar is " << (bar ? "not empty!n" : "emptyn");
    }
    std::cin.get();
    return 0;
}

练习
#include 
#include 

using namespace std;

class TestPtr {
public:
    TestPtr() :name("default")
    {
        std::cout << __func__ << " : " << name << "n";
    }
    TestPtr(const char *_name) :name(_name)
    {
        std::cout << __func__ << " : " << name << "n";
    }
    ~TestPtr()
    {
        std::cout << __func__ << " : " << name << "n";
    }

    void PrintName(void)
    {
        std::cout << "Name:"  << name << "n";
    }
private:
    std::string name;
};

void Test()
{
    TestPtr* p4(nullptr);
    int i = 1;
    {
        std::unique_ptr p3(new TestPtr("p3"));

        {
            std::unique_ptr p0(new TestPtr("p0")); // 方式一
            std::cout << '[' << i++ << "] p0:" << p0.get() << "n";
            std::unique_ptr p1 = std::move(p0); // 移动p0的对象到p1, 内存不释放
            std::cout << '[' << i++ << "] after p0 calls move    :" << p0.get() << "n"; // 无效地址:唯一指针,转移后为本身指向nullptr
            std::cout << '[' << i++ << "] after p0 is moved to p1:" << p1.get() << "n"; // 有效地址:指向p0原来指向的地址
            p1.reset(); // 主动释放p1的内存
            std::cout << '[' << i++ << "] after reset p1:" << p1.get() << "n"; // 无效地址:主动调用析构释放内存

            std::unique_ptr p2 = std::make_unique("p2"); // 方式二
            std::cout << '[' << i++ << "] p2:" << p2.get() << "n";

            p4 = p3.release(); // 释放p3对象存储内存所有权,返回给p4
            p3 = std::move(p2); // 移动p2的对象到p3, 对象的内存不释放,p3的对象内存自动释放
            std::cout << '[' << i++ << "] after p2 calls move    :" << p2.get() << "n"; // 无效地址:唯一指针,转移后为本身指向nullptr
            std::cout << '[' << i++ << "] after p2 is moved to p3:" << p3.get() << "n"; //  有效地址:指向p2原来指向的地址
        } // p3 内存不释放

        p3->PrintName(); // name:p2

        p4->PrintName(); // name: p3
    } // 离开作用域后析构函数自动释放 p3的内存

    if (p4)
    {
        std::cout << "p4 is not empty ptr, need manual delete it!n";
        delete p4; // 手动释放p3对象的内存,不释放就内存泄露
        p4 = nullptr;
    }
    else
    {
        std::cout << "p4 is empty ptr,good!n";
    }
}


int main()
{
    Test();
    std::cin.get();
    return 0;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1013572.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号