智能指针--转

1、智能指针的作用

  C++程序设计设计中使用堆内存是非常频繁的操作,堆内存的申请和释放都由程序员自己管理。程序员自己管理内存可以提高程序的效率,但是整体来说堆内存的管理是麻烦的,C++11中引入了智能指针的概念,方便管理内存。使用普通指针,容易造成堆内存泄露(忘记释放),二次释放,程序发生异常时内存泄露等问题,使用智能指针能更好的管理堆内存。

智能指针从下面三个层次理解:

  1、从较浅的层面,智能指针是利用叫做RALL(资源获取即初始化)的技术对普通的指针进行封装,这使得智能指针实质是一个对象,行为表现的却像一个指针。

  2、智能指针的作用是防止忘记调用delete释放内存和程序异常的进入catch块忘记释放内存。另外指针的释放时机也是非常有讲究的,多次释放同一个指针会造成程序崩溃,这些都可以通过智能指针来解决。

  3、智能指针还有一个作用是把值语义转换成引用语义。

2、智能指针的使用

智能指针在C++11版本之后提供,包含在头文件<memory>中,shared_ptr、unique_ptr、weak_ptr

2.1、shared_ptr的使用

shared_ptr多个指针指向相同的对象。shared_ptr使用引用计数,每一个shared_ptr的拷问都指向相同的内存。每使用它一次,内部的引用计数加1,每析构一次,内部的引用计数减1,减为0时,自动删除所指向的堆内存。

shared_ptr内部的引用计数是线程安全的,但是对象的读取需要加锁。

  1、初始化。智能指针是个模板类,可以指定类型,传入指针通过构造函数初始化。也可以使用make_share函数初始化。不能将指针直接赋值给一个智能指针,一个是类,一个是智能指针。

  2、拷贝和赋值。拷贝使得对象的引用计数增加1,赋值使得原对象引用计数减1,当计数为0时,自动释放内存。后来指向的对象引用计数加1,指向后来的对象。

  3、get函数获取原始指针。

  4、注意不要用一个原始指针初始化多个shared_ptr,否则会造成二次释放同一内存。

  5、注意避免循环引用,shared_ptr的一个最大的陷阱是循环引用,循环引用会导致堆内存无法正确释放,导致内存泄露。循环引用在weak_ptr中介绍。

#include<bits/stdc++.h>
using namespace std;

int main(){
    int a=10;
    shared_ptr<int> spa1=make_shared<int>(a);//最安全的分配和使用动态内存的标准库函数,它在动态内存中分配一个对象并初始化它,返回一个指向此对象的shared_ptr
    shared_ptr<int> spa2(spa1);//copy
    cout<<spa1.use_count()<<endl;//2

    int b=20;
    int *p=&a;
    //shared_ptr<int> sp3=p; 错误
    shared_ptr<int> spb1=make_shared<int>(b);
    spa2=spb1;
    p=spb1.get();//获取原始指针

    cout<<spa1.use_count()<<endl;//1
    cout<<spb1.use_count()<<endl;//2
    cout<<*spa1<<endl;//10
    cout<<*spa2<<endl;//20
    cout<<*spb1<<endl;//20
    return 0;
}

2.2、unique_ptr的使用

unique_ptr“唯一”拥有其所指向对象,同一时刻只能有一个unique_ptr指向给定对象(通过禁止拷贝语义、只有移动语义来实现)。相比与原始指针unique_ptr用于其RALL的特性,使得在出现异常的情况下,动态资源能得到释放。unique_ptr指针本身的生命周期:从unique_ptr指针创建时开始,直到离开作用域。离开作用域时,则将其所指对象销毁(默认使用delete操作符,用户可以指定其它操作)。unique_ptr指针与其所指对象的关系:在智能指针生命周期内,可以改变智能指针所指对象,如创建智能指针时通过构造函数指定、通过reset方法重新指定、通过release方法释放所有权、通过移动语义转移所有权。

#include<bits/stdc++.h>
using namespace std;

int main(){
    unique_ptr<int> up(new int(10)); //绑定动态对象
//    unique_ptr<int> up1=up;  不能赋值
//    unique_ptr<int> up2(up);  不能拷贝
    cout<<*up<<endl;
    if(up) cout<<"up指向了一个对象"<<endl; //up指向了一个对象
    else cout<<"up并没有指向了一个对象"<<endl;

    unique_ptr<int> up3=move(up); //转换所有权
    cout<<*up3<<endl;
    if(up) cout<<"up指向了一个对象"<<endl;
    else cout<<"up并没有指向了一个对象"<<endl; //up并没有指向了一个对象

    up.release(); //释放所有权
    return 0;
}

2.3、weak_ptr的使用

weak_ptr是为了配合shared_ptr而引入的一种智能指针,因为它不具有普通指针的行为,没有重载operator*和->,它的最大作用在于协助shared_ptr工作,像旁观者那样观测资源的使用情况。weak_ptr可以从一个shared_ptr或者另一个weak_ptr对象构造,获得资源的观测权。但weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加。一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放,即使有weak_ptr指向对象,对象也会被释放。

weak_ptr<T> w  //空weak_ptr可以指向类型为T的对象

w.reset()  //将w置空

w.use_count()  //与w共享对象的shared_ptr的数量

w.expired()  //若w.use_count()为0,返回true,否则返回false

w.lock()  //如果expired为true,返回一个空shared_ptr,否则返回一个指向w的对象的shared_ptr

#include<bits/stdc++.h>
using namespace std;

int main(){
    shared_ptr<int> sp=make_shared<int>(10);
    cout<<sp.use_count()<<endl;//1

    weak_ptr<int> wp(sp);
    cout<<wp.use_count()<<endl;//1

    if(!wp.expired()){
        shared_ptr<int> sp1=wp.lock();
        *sp=100;
        cout<<wp.use_count()<<endl;//2
    }
    return 0;
}

参考地址:https://www.cnblogs.com/wxquare/p/4759020.html、《C++ primer》

原文地址:https://www.cnblogs.com/ybf-yyj/p/9649986.html

时间: 2024-08-11 12:49:45

智能指针--转的相关文章

智能指针的原理和简单实现

什么是智能指针? 智能指针实质上是一个类,定义一个类来封装资源的分配和释放.这个类的构造函数中传入一个指针,完成资源的分配和初始化.在析构函数中释放传入的该指针,完成资源的释放. 为什么要用智能指针? 智能指针就是智能,自动化的管理指针所指向的动态资源. 例如以下情况:代码中经常会忘记释放动态开辟的内存资源,导致内存泄露. // case1 void Test2() {  int* p1 = new int(2);  bool isEnd = true;  //...  if (isEnd)  

实战c++中的智能指针unique_ptr系列-- 使用std::unique_ptr代替new operator(错误:‘unique_ptr’ is not a member of ‘std’)

写了很多篇关于vector的博客,其实vector很便捷,也很简单.但是很多易错的问题都是vector中的元素为智能指针所引起的.所以决定开始写一写关于智能指针的故事,尤其是unique_ptr指针的故事. 这是个开始,就让我们使用std::unique_ptr代替new operator吧! 还是用程序说话: #include<iostream> int main() { while (true) int *x = new int; } 看下任务管理器中的内存: 此时使用智能指针unique

C++智能指针简单剖析

导读 最近在补看<C++ Primer Plus>第六版,这的确是本好书,其中关于智能指针的章节解析的非常清晰,一解我以前的多处困惑.C++面试过程中,很多面试官都喜欢问智能指针相关的问题,比如你知道哪些智能指针?shared_ptr的设计原理是什么?如果让你自己设计一个智能指针,你如何完成?等等--.而且在看开源的C++项目时,也能随处看到智能指针的影子.这说明智能指针不仅是面试官爱问的题材,更是非常有实用价值. 下面是我在看智能指针时所做的笔记,希望能够解决你对智能指针的一些困扰. 目录

boost智能指针使用

#include <iostream> #include <tr1/memory> #include <boost/scoped_ptr.hpp> //scoped_ptr还不属于tr1 #include <boost/scoped_array.hpp> //scored_array也不属于tr1 #include <boost/shared_array.hpp> //shared_array也不属于tr1 class CTest { publi

webkit智能指针 - RefPtr, PassRefPtr

历史 2005年之前,Webkit中很多对象都采用引用计数的方式.它们通过继承RefCounted]类模板来实现这种模式.RefCounted主要是实现了ref()和deref()两个函数.在需要引用对象时要调用ref()增加引用计数,在不再需要对象时,要调用deref()函数减少引用计数.ref()和deref()需要成对出现.这和使用new/delete一样,多调用.少调用.没调用的问题总是时有发生.如果能由编译器自动完成ref, deref的调用,C/C++编程的bug至少也可以减少一半以

智能指针tr1::shared_ptr、boost::shared_ptr使用

对于tr1::shared_ptr在安装vs同时会自带安装,但是版本较低的不存在.而boost作为tr1的实现品,包含 "Algorithms Broken Compiler Workarounds Concurrent Programming Containers Correctness and Testing Data Structures Domain Specific Function Objects and Higher-order Programming Generic Progra

C++ Primer笔记8_动态内存_智能指针

1.动态内存 C++中,动态内存管理是通过一对运算符完成的:new和delete.C语言中通过malloc与free函数来实现先动态内存的分配与释放.C++中new与delete的实现其实会调用malloc与free. new分配: 分配变量空间: int *a = new int; // 不初始化 int *b = new int(10); //初始化为10 string *str = new string(10, ); 分配数组空间: int *arr = new int[10];//分配的

C++之智能指针20170920

/******************************************************************************************************************/ 一.C++智能指针_自己实现智能指针 1.使用局部变量结合new的方式,防止new导致的内存泄漏 class sp { private: Person *p; public: sp() : p(0) {}//表明sp的构造函数 继承person的无参构造函数 sp(

智能指针简介

智能指针用于解决常规指针所带来的内存泄露.重复释放.野指针等内存问题.智能指针基于这样的事实得以发挥作用:定义在栈中的智能指针,当超出其作用域时,会自动调用它的析构函数,从而可以释放其关联的内存资源. 之前C++标准库中定义的智能指针std::auto_ptr<T>,因其设计存在缺陷,所以已不再推荐使用.C++11引入了新的智能指针:unique_ptr.shared_ptr和weak_ptr. 一:unique_ptr unique_ptr类似于auto_ptr.两个unique_ptr实例

C++智能指针剖析(下)boost::shared_ptr&amp;其他

1. boost::shared_ptr 前面我已经讲解了两个比较简单的智能指针,它们都有各自的优缺点.由于 boost::scoped_ptr 独享所有权,当我们真真需要复制智能指针时,需求便满足不了了,如此我们再引入一个智能指针,专门用于处理复制,参数传递的情况,这便是如下的boost::shared_ptr. boost::shared_ptr 属于 boost 库,定义在 namespace boost 中,包含头文件#include<boost/smart_ptr.hpp> 便可以使