weak_ptr指针编程实验

  • 基本知识
    • weak_ptr
    • 改进后的StrBlob类
  • 示例代码
    • my_StrBlob.h
    • main.cpp
    • 运行结果

本文是本人大一期间在校学习C++课程时所撰写的实验报告的摘录,由于刚上大学,刚接触计算机编程方面的相关知识,故可能会有很多不足甚至错误的地方,还请各位看官指出及纠正。
本文所涉及到的“教材”指:
电子工业出版社《C++ Primary中文版(第5版)》
如需转载或引用请标明出处。

基本知识

weak_ptr

weak_ptr是一种不控制所指向对象生存期的智能指针,它指向由一个shared_ptr管理的对象。将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放。即使有weak_ptr指向对象,对象也还是会被释放,因此,weak_ptr的名字体现了“弱”共享对象的特点。

下面是关于weak_ptr的一些操作:

weak_ptr<T> w                      //空weak_ptr可以指向类型为T的对象
weak_ptr<T> w(sp)                 //与shared_ptr sp指向相同对象的weak_ptr。T必须能转换为sp指向的类型
w.reset()                           //将w值为空
w.lock()                            //如果与w共享对象的shared_ptr数量为0,则返回一个空shared_ptr;否则返回一个指向w的对象的shared_ptr

更多相关操作详见教材P420,表12.5。

当我们创建一个weak_ptr时,要用一个shared_ptr来初始化它

auto p = make_shared<int>(99);
weak_ptr<int> wp(p);

由于weak_ptr的“弱”的特性,创建wp并不会增加p的引用计数,因此wp所指向的对象可能会被释放掉。由于对象可能不存在,我们不能使用weak_ptr直接访问对象,因而必须调用weak_ptr的成员函数lock,该函数检查weak_ptr指向的对象是否存在。若存在,lock返回一个指向共享对象的shared_ptr,否则返回一个空的shared_ptr。

改进后的StrBlob类

关于StrBlob类可以看这篇文章。

为了做到不影响给定的StrBlob所指向vector的生存期,同时也可以阻止用户访问一个不再存在的vector的目的,将给以前的StrBlob定义一个伴随指针类StrBlobPtr。该类会保存一个weak_ptr,在初始化时使它指向StrBlob的成员data。

StrBlobPtr有两个数据成员:weak_ptr类型的wptr,指向空或者一个StrBlob中的vector;vector::size_type类型的curr,用于保存当前对象所表示的元素的下标(实际上是给shared_ptr使用的下标)。此外还将有一个成员函数check用于检查解引用StrBlobPtr是否安全,另一个成员函数deref用于解引用对象。

在StrBlob中,添加了两个成员函数begin和end,用于代替普通begin函数和end函数的作用(返回对应的迭代器),新定义的这两个函数将使用StrBlobPtr以免在for循环中改变StrBlob中data的引用计数。为了做到检查指向位置是否合法的同时可以方便地解引用,让StrBlobPtr的成员函数check在检查通过时返回对应的shared_ptr,因此成员函数deref实际上是间接地通过解引用一个shared_ptr来获得weak_ptr指向对象,又因为是在函数中,故不会影响指向对象的生存期

示例代码

my_StrBlob.h

#ifndef MY_STRBLOB_H
#define MY_STRBLOB_H
#include <vector>
#include <string>
#include <memory>
//包含标准库类型initializer_list,以使用有可变形参的函数
#include <initializer_list>
//包含并使用一些标准库异常
#include <stdexcept>using namespace std;                                                                                                                                                   class StrBlobPtr;      //提前声明,StrBlob中的友类声明所需//定义StrBlob类
class StrBlob
{friend class StrBlobPtr;                                       //友元声明,声明StrBlobPtr是StrBlob的友元//public的成员可被整个程序使用
public:typedef vector<string>::size_type size_type;                   //定义vector<string>的size_type类型为size_typeStrBlob();                                                        //无形参的构造函数声明StrBlob(initializer_list<string> list);                           //有可变形参的构造函数声明size_type size() const { return data->size(); }                    //定义StrBlob的成员函数sizebool empty() const { return data->empty(); }                 //定义StrBlob的成员函数empty//添加和删除元素的操作void push_back(const string& t) { data->push_back(t); }         //定义StrBlob的成员函数push_backvoid pop_back();                                               //StrBlob的成员函数pop_back的声明                                                                                                                                       //访问元素的操作string& front();                                               //StrBlob的成员函数front的声明const string& front() const;                                  //const版本的StrBlob的成员函数front的声明string& back();                                                   //StrBlob的成员函数back的声明const string& back() const;                                        //const版本的StrBlob的成员函数back的声明//提供给StrBlobPtr的接口,定义StrBlobPtr后才能定义这两个函数StrBlobPtr begin();                                                //StrBlob的成员函数begin的声明StrBlobPtr end();                                             //StrBlob的成员函数end的声明//private的成员只能被类的成员函数访问
private:shared_ptr<vector<string>> data;                                //该类只有一个成员:指向存储string的vector的智能指针void check(size_type i, const string& msg) const;               //如果data[i]不合法,抛出一个异常,显示msg
};StrBlob::StrBlob() :data(make_shared<vector<string>>()) { }           //定义无形参的构造函数
StrBlob::StrBlob(initializer_list<string> list) : data(make_shared<vector<string>>(list)) { }  //定义有可变形参的构造函数void StrBlob::check(size_type i, const string& msg) const            //check函数的定义
{if (i >= data->size())                                          //如果i超出vector的范围throw out_of_range(msg);                                    //则抛出异常
}string& StrBlob::front()                                           //普通版本的front函数
{check(0, "front on empty StrBlob");                              //如果vector为空,则check抛出一个异常return data->front();                                            //返回data的成员函数front的返回值(起始元素的引用)
}const string& StrBlob::front() const                               //const版本的front函数
{check(0, "front on empty StrBlob");                              //如果vector为空,则check抛出一个异常return data->front();                                            //返回data的成员函数front的返回值(起始元素的引用)
}string& StrBlob::back()                                                //普通版本的back函数
{check(0, "back on empty StrBlob");                               //如果vector为空,则check抛出一个异常return data->back();                                         //返回data的成员函数back的返回值(尾元素的引用)
}const string& StrBlob::back() const                                    //const版本的back函数
{check(0, "back on empty StrBlob");                               //如果vector为空,则check抛出一个异常return data->back();                                         //返回data的成员函数back的返回值(尾元素的引用)
}void StrBlob::pop_back()                                           //定义SrtBlob的成员函数pop_back
{check(0, "pop_back on empty StrBlob");                           //如果vector为空,则check抛出一个异常data->pop_back();                                                //返回data的成员函数pop_back的返回值
}class StrBlobPtr
{friend bool eq(const StrBlobPtr& lhs, const StrBlobPtr& rhs);  //声明函数eq是StrBlobPtr是的友元函数public:StrBlobPtr() :curr(0) { }                                           //无形参的构造函数定义(弱指针位置指向首元素)StrBlobPtr(StrBlob& a, size_t sz = 0) :wptr(a.data), curr(sz) { }    //有形参的构造函数定义(默认位置是首元素)                                                                                                                                                              string& deref() const;                                                //StrBlobPtr的成员函数deref的声明StrBlobPtr& incr();                                                    //StrBlobPtr的成员函数incr的声明StrBlobPtr& decr();                                                 //StrBlobPtr的成员函数decr的声明private:weak_ptr<vector<string>> wptr;                                      //成员wptr:一个指向vector<string>的weak_ptrsize_t curr;                                                       //成员curr:用于指示vector中的当前位置shared_ptr<vector<string>> check(size_t i, const string& msg) const;    //check函数,
};//如果wptr指向的对象不存在,或位置超出vector,则抛出相应的异常
shared_ptr<vector<string>> StrBlobPtr::check(size_t i, const string& msg) const
{auto ret = wptr.lock();                           //ret是一个指向vector<string>的shared_ptrif (!ret)                                      //如果wptr指向的对象不存在throw runtime_error("unbound StrBlobPtr");if (i >= ret->size())                            //如果指向的位置超出vectorthrow out_of_range(msg);return ret;                                        //返回相应的shared_ptr
}string& StrBlobPtr::deref() const                  //解引用指向当前位置的shared_ptr
{auto p = check(curr, "dereference past end");   //检查当前位置是否合法return (*p)[curr];                              //返回当前位置的解引用
}StrBlobPtr& StrBlobPtr::incr()                     //递增weak_ptr指向的位置
{check(curr, "increment past end of StrBlobPtr");//检查位置curr++;                                          //递增指向位置return *this;                                   //返回当前的StrBlobPtr
}StrBlobPtr& StrBlobPtr::decr()
{curr--;                                            //递减指向位置check(-1, "decrement past begin of StrBlobPtr");//检查位置return *this;                                   //返回当前的StrBlobPtr
}StrBlobPtr StrBlob::begin()
{return StrBlobPtr(*this);                      //返回一个弱指针指向StrBlob成员data首元素的StrBlobPtr
}//返回一个弱指针指向StrBlob成员data尾元素的StrBlobPtr
StrBlobPtr StrBlob::end()
{auto ret = StrBlobPtr(*this, data->size());        //更改构造函数默认参数为data的大小,使弱指针指向尾元素return ret;
}bool eq(const StrBlobPtr& lhs, const StrBlobPtr& rhs)
{auto l = lhs.wptr.lock(), r = rhs.wptr.lock();if (l == r)                                      //如果两个shared_ptr指向同一位置return (!r || lhs.curr == rhs.curr);        //则返回ture(r与l可能指向空)elsereturn false;
}bool neq(const StrBlobPtr& lhs, const StrBlobPtr& rhs)
{return !eq(lhs, rhs);                          //上个函数的相反
}#endif

main.cpp

#include <iostream>
#include "my_StrBlob.h"                                       //包含自定义的头文件用双引号int main(void)
{StrBlob b1;                                                //用无形参的构造函数初始化StrBlob类型b1{StrBlob b2({ "China", "America", "Japan" });        //用有可变形参的构造函数初始化StrBlob类型b2b1 = b2;                                            //将b2的值赋给b1b2.push_back("France");                                //在b2末尾添加元素“France”cout << b2.size() << endl;                           //输出b2}//b2的作用域结束,其智能指针的的计数器减一                                                                                                                                                          cout << b1.size() << endl;                               //使用自定义的成员函数size输出b1的大小cout << b1.front() << " " << b1.back() << endl;            //使用自定义的成员函数front、back输出b1的首位两个元素b1.pop_back();                                         //删除b1的尾元素const StrBlob b3 = b1;                                   //复制一份const的b1给b3,b1智能指针的计数器加一cout << b3.front() << " " << b3.back() << endl;          //使用const版本的自定义的成员函数front、back输出b3的首位两个元素for (auto it = b1.begin(); neq(it, b1.end()); it.incr())//使用弱指针遍历b1,以免影响其计数器的值cout << it.deref() << endl;system("pause");return 0;
}

运行结果

weak_ptr指针编程实验相关推荐

  1. 共享智能指针编程实验

    共享智能指针编程实验 基本知识 shared_ptr与make_shared initializer_list 自定义的StrBlob类 const限定符 示例代码 my_StrBlob.h main ...

  2. 实验六 Linux进程编程,Linux系统编程实验六:进程间通信

    <Linux系统编程实验六:进程间通信>由会员分享,可在线阅读,更多相关<Linux系统编程实验六:进程间通信(10页珍藏版)>请在人人文库网上搜索. 1.实验六:进程间通信l ...

  3. allocator类编程实验

    allocator类编程实验 基本知识 allocator uninitialized_copy.uninitialized_fill等函数 示例程序 示例代码 usealloc.cpp useall ...

  4. 182_赵陈雄_java核心编程实验

    Java-核心编程实验课笔记(一) 一:Java特性和优势 1:简单性 2:面向对象 3:可移植性 4:高性能 5:分布式 6:动态性 7:多线程 8:安全性 9:健壮性 二:Java程序运行机制 1 ...

  5. 实验c语言程序数据类型,C语言编程实验.doc

    C语言编程实验.doc C语言程序设计上机安排C语言上机实验32学时序号实验项目名称内容提要学时数1上机操作初步熟悉VC语言上机环境:了解如何编辑.编译.连接和运行一个C程序.22简单的C程序设计掌握 ...

  6. 计算机编程实验,c语言下的计算机软件编程实验

    c语言下的计算机软件编程实验 (5页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.90 积分 C语言下的计算机软件编程实验 摘 要C语言是计算机应用的 ...

  7. ## ARM基础编程实验

    ARM基础编程实验 作者: Saint 掘金:https://juejin.im/user/5aa1f89b6fb9a028bb18966a 微博:https://weibo.com/54582774 ...

  8. 华中科技大学计算机通信与网络实验,华中科技大学计算机通信与网络实验报告Socket编程实验.docx...

    实验一 Socket编程实验 1.1环境 开发环境:Windows 10 64 位,Intel Core i5-7300HQ CPU, 8GB 内存 1.1. 1开发平台 Microsoft Visu ...

  9. C Primer Plus (第五版) 第十章 数组和指针 编程练习

    第十章 数组和指针 编程练习 1.修改程序清单10.7中的程序rain,使它不使用数组下标,而是使用指针进行计算(程序中仍然需要声明并初始化数组). # include <stdio.h> ...

最新文章

  1. 结构体名和结构体名是个指针的区别
  2. 【vs开发】向图形界面程序添加控制台
  3. 机器学习样本标记 示意代码
  4. 线上直播 | NVIDIA TensorRT在神经机器翻译中的应用
  5. MVC学习二:基础语法
  6. 一次性定时器 setTimeout
  7. 010 editor 应用templates分析ELF和dex文件
  8. C语言equivalent用法,C语言相当于'setw'函数
  9. mysql如何创建视图
  10. mysql 无法创建sock,mysql.sock无法打开的问题
  11. Linux (deepin)网络管理详解.
  12. 看懂Python爬虫框架,所见即所得一切皆有可能
  13. 文学研究助手(设计性实验)
  14. 【Linux集群教程】12 集群安全防御 - 安全防御概述和Linux防火墙
  15. 英特尔one API——AI为科技加速
  16. 高通骁龙845的android手机有哪些,骁龙845手机有哪些?高通骁龙845手机推荐
  17. 金蝶K3供应链与总账对账的思路及方法
  18. 如何把照片转换成3D?告这篇文章告诉你
  19. iOS-基础控件--UITbleViewCell的自定义(高度自适应方法简单封装)
  20. 计算机游戏设计软件有哪些,除了玩游戏还能做设计?十代酷睿设计软件实操

热门文章

  1. 如何测得存储空间大小
  2. CentOS 6.7编译安装PHP7
  3. tablefunc 行转列
  4. 【Python数据挖掘课程】七.PCA降维操作及subplot子图绘制
  5. Python之字符串的134个常用操作
  6. 【数据结构与算法】之深入解析“不同的二叉搜索树II”的求解思路与算法示例
  7. iOS之CocoaPods二进制化的实现方案
  8. 【数据结构与算法】之连通网络的操作次数的算法
  9. 【数据结构与算法】之判断字符是否唯一
  10. 【机器视觉】 dev_set_contour_style算子