智能指针的总结

定义

智能指针是对象,不是指针。它是通过c++的RAII机制实现的,主要是利用c++对象在释放资源的时候,会自动调用析构函数这一特性。

分类

auto_ptr: 智能指针,c++11已经停用;

shared_ptr: 强智能指针,可以改变资源的引用计数;

weak_ptr: 弱智能指针,不会改变资源的引用计数;

unique_ptr: 独占式强智能指针,只能转移,不能重新赋值;

智能指针的使用

shared_ptr

原理

shared_ptr采用了引用计数器,允许多个指针指向同一个对象。每一个shared_ptr的拷贝都指向相同的内存,并共同维护同一个引用计数器,记录统一使用被引用的次数。每增加一个shared_ptr智能指针对象,new对象指针的引用计数上就加1,当shared_ptr智能指针失效时,new对象指针的引用计数就减1。引用计数归0时,shared_ptr会释放管理的内存空间。

shared_ptr包含2个指针,一个是指向管理的内存空间,一个是指向内存的控制块。

内存控制块包含引用计数器,删除器,分配器等。

class Test
{
public:
    Test();
    ~Test();

    void setFather(std::shared_ptr<Test> &value) {
        m_father = value;
    }

    void setSon(std::shared_ptr<Test> &value) {
        m_son = value;
    }

private:
    std::shared_ptr<Test> m_father;
    std::shared_ptr<Test> m_son;
};

void test() {
    Test *ps = new Test();
    std::shared_ptr<Test> ptr1(ps);
    std::shared_ptr<Test> ptr2(ps);

    ptr1->setFather(ptr2);
    ptr2->setSon(ptr1);

    //计数
    std::cout << ptr1.use_count() << endl;
    //计数
    std::cout << ptr2.use_count() << endl;

    //计数获取原始指针
    std::cout << ptr1.get() <<endl;
    std::cout << ptr2.get() <<endl;
}

输出:
Test Construct()
2
2
0xfe1740
0xfe1740

从输出信息中可以看到并未调用析构函数。主要是因为互相引用导致。

示例2 测试引用计数问题

//测试shared_ptr的引用计数
void testSharedPtrCount() {
    //不要使用该方式初始化
    Test *ps = new Test();
    std::shared_ptr<Test> ptr1(ps);
    std::shared_ptr<Test> ptr2(ps);

    //计数
    std::cout << ptr1.use_count() << endl;
    std::cout << ptr2.use_count() << endl;

    std::shared_ptr<Test> ptr3(new Test());
    std::shared_ptr<Test> ptr4 = ptr3;

    //计数
    std::cout << ptr3.use_count() << endl;
    std::cout << ptr4.use_count() << endl;
}

输出:
1
1
2
2

可以看到使用同一个对象指针初始化的时候,引用计数为1,而使用智能指针初始化智能指针后,引用计数均为2。

智能指针的头文件为:#include

weak_ptr

weak_ptr不能单独作为智能指针使用,只能辅助shared_ptr解决循环依赖的问题。

定义对象的时候使用shared_ptr,引用对象的时候使用weak_ptr

修改shared_ptr的代码为:

class Test
{
public:
    Test();
    ~Test();

    void setFather(std::shared_ptr<Test> &value) {
        m_father = value;
    }

    void setSon(std::shared_ptr<Test> &value) {
        m_son = value;
    }

private:
    //修改对象的引用为weak_ptr
    std::weak_ptr<Test> m_father;
    std::weak_ptr<Test> m_son;
};

输出:
Test Construct()
1
1
0x1091740
0x1091740
Test Destruct()
Test Destruct()

可以看到析构函数被调用了。(即使析构了2次,部分编译器可能不会出现析构错误信息)

unique_ptr

unique_ptr是独占型的强智能指针。独占型就是不允许多个智能指针指向同一块内存空间,也不支持拷贝,复制。

示例1 独占性

//测试uniqueptr
void testUniquePtr() {
    Test *ps = new Test();
    std::unique_ptr<Test> ptr1(ps);
    //编译期间就出现错误
    std::unique_ptr<Test> ptr2 = ptr1;

    std::cout << ptr1.get() << endl;
    std::cout << ptr2.get() << endl;
}

**示例2 move **

//测试unique_ptr的转移
void testUniquePtrMove() {
    Test *ps = new Test();
    std::unique_ptr<Test> ptr1(ps);

    std::cout << "Ptr1: " << ptr1.get() << endl;

    std::unique_ptr<Test> ptr2(ps);
    ptr2 = std::move(ptr1);

     std::cout << "Ptr1: "  << ptr1.get() << endl;
     std::cout << "Ptr2: "  << ptr2.get() << endl;
}

//输出
Test Construct()
Ptr1: 0x761740
Test Destruct()
Ptr1: 0
Ptr2: 0x761740
Test Destruct()

可以看出调用move()后,ptr1被置为nullptr(0), ptr2被设置为0x761740

常见的陷阱
  • 不要使用指针初始化多个智能指针。

  • 不要delete get()返回的指针。

总结

  1. 智能指针是对象而不是指针。
  2. 智能指针解决的是动态内存管理的问题(堆内存)。
  3. shared_ptr的循环依赖问题通过weak_ptr来解决,weak_ptr不拥有对象的所有权,一个share_ptr可对应多个weak_ptr
  4. unique_ptr可算作auto_ptr的翻版,不允许多个unique_ptr持有同一个对象。
  5. auto_ptr已经被弃用。

参考地址

C++ 智能指针

c++智能指针

C++智能指针的使用(非常详细)

C++智能指针详解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值