【cmu15445c++入门】(5)C++ 包装类(管理资源的类)

一、背景

c++包装类

二、运行代码 


// A C++ wrapper class is a class that manages a resource. A resource
// could be memory, file sockets, or a network connection. Wrapper classes
// often use the RAII (Resource Acquisition is Initialization) C++ 
// programming technique. Using this technique implies that the resource's
// lifetime is tied to its scope. When an instance of the wrapper class is
// constructed, this means that the underlying resource it is managing is
// available, and when this instance is destructed, the resource also
// is unavailable. 

//C++ 包装类是管理资源的类。资源可以是内存、文件套接字或网络连接。
//包装类通常使用 RAII(资源获取即初始化)C++ 编程技术。
//使用此技术意味着资源的生存期与其范围相关联。
//当构造包装类的实例时,这意味着它所管理的基础资源是可用的,而当此实例被销毁时,该资源也是不可用的。

// Here are a couple resources on RAII that are useful:
// https://en.cppreference.com/w/cpp/language/raii (RAII docs on the CPP
// docs website)
// Interesting Stack Overflow answers to "What is meant by RAII?":
// https://stackoverflow.com/questions/2321511/what-is-meant-by-resource-acquisition-is-initialization-raii

// In this file, we will look at a basic implementation of a wrapper class that
// manages an int*. We will also look at usage of this class.

// Includes std::cout (printing) for demo purposes.
#include <iostream>
// Includes the utility header for std::move.
#include <utility>

// The IntPtrManager class is a wrapper class that manages an int*. The
// resource that this class is managing is the dynamic memory accessible via
// the pointer ptr_. By the principles of the RAII technique, a wrapper class
// object should not be copyable, since one object is supposed to manage one
// resource. Therefore, the copy assignment operator and copy constructor are
// deleted from this class. However, the class is still moveable from different
// lvalues/owners, and has a move constructor and move assignment operator.
// Another reason that wrapper classes forbid copying is because they destroy
// their resource in the destructor, and if two objects are managing the same
// resource, there is a risk of double deletion of the resource.
// IntPtrManager 类是管理 int* 的包装类。此类管理的资源是通过指针ptr_访问的动态内存。
// 根据 RAII 技术的原则,包装类对象不应该是可复制的,因为一个对象应该管理一个资源。
// 因此,从此类中删除复制赋值运算符和复制构造函数。但是,该类仍然可以从不同的左值/所有者移动,并且具有移动构造函数和移动赋值运算符。
// 包装类禁止复制的另一个原因是在析构函数中进行做资源销毁,如果两个对象管理同一资源,则存在双重删除资源的风险。

class IntPtrManager {
  public:
    // All constructors of a wrapper class are supposed to initialize a resource.
    // In this case, this means allocating the memory that we are managing.
    // The default value of this pointer's data is 0.
    IntPtrManager() {
      ptr_ = new int;
      *ptr_ = 0;
    }

    // Another constructor for this wrapper class that takes a initial value.
    IntPtrManager(int val) {
      ptr_ = new int;
      *ptr_ = val;
    }

    // Destructor for the wrapper class. The destructor must destroy the
    // resource that it is managing; in this case, the destructor deletes
    // the pointer!
    ~IntPtrManager() {
      // Note that since the move constructor marks objects invalid by setting
      // their ptr_ value to nullptr, we have to account for this in the 
      // destructor. We don't want to be calling delete on a nullptr!
      std::cout << "~IntPtrManager()" << std::endl;
      if (ptr_) {
        std::cout << "ptr is  " << ptr_ <<std::endl;
        delete ptr_;
      }
    }

    // Move constructor for this wrapper class. Note that after the move
    // constructor is called, effectively moving all of other's data into
    // the specified instance being constructed, the other object is no
    // longer a valid instance of the IntPtrManager class, since it has
    // no memory to manage. 
    IntPtrManager(IntPtrManager&& other) {
      ptr_ = other.ptr_;
      other.ptr_ = nullptr;
    }

    // Move assignment operator for class Person. Similar techniques as
    // the move constructor.
    IntPtrManager &operator=(IntPtrManager &&other) {
      ptr_ = other.ptr_;
      other.ptr_ = nullptr;
      return *this;
    }

    // We delete the copy constructor and the copy assignment operator,
    // so this class cannot be copy-constructed. 
    IntPtrManager(const IntPtrManager &) = delete;
    IntPtrManager &operator=(const IntPtrManager &) = delete;

    // Setter function.
    void SetVal(int val) {
      *ptr_ = val;
    }

    // Getter function.
    int GetVal() const {
      return *ptr_;
    }

  private:
    int *ptr_;

};

int main() {
  // We initialize an instance of IntPtrManager. After it is initialized, this
  // class is managing an int pointer.
  IntPtrManager a(445);

  // Getting the value works as expected.
  std::cout << "1. Value of a is " << a.GetVal() << std::endl;

  // Setting the value goes through, and the value can retrieved as expected.
  a.SetVal(645);
  std::cout << "2. Value of a is " << a.GetVal() << std::endl;

  // Now, we move the instance of this class from the a lvalue to the b lvalue
  // via the move constructor.
  IntPtrManager b(std::move(a));

  // Retrieving the value of b works as expected because b is now managing the
  // data originally constructed by the constructor that created a. Note that
  // calling GetVal() on a will segfault, and a is supposed to effectively be
  // empty and unusable in this state.
  std::cout << "Value of b is " << b.GetVal() << std::endl;
  // 此时去访问a必然会报错退出
  //std::cout << "Value of a is " << a.GetVal() << std::endl;

  IntPtrManager c = std::move(b);
  std::cout << "Value of c is " << c.GetVal() << std::endl;
  c.SetVal(123);
  
  // Once this function ends, the destructor for both a and b will be called.
  // a's destructor will note that the ptr_ it is managing has been set to 
  // nullptr, and will do nothing, while b's destructor should free the memory
  // it is managing.
  // 在函数退出之后,会有析构函数

  return 0;
}

三、运行结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/366204.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

printf死翘翘

本来想把我的单片机玩一下&#xff0c;寄给在大学搞研究的一个朋友&#xff0c;但竟然挂在printf里面&#xff0c;大概知道是什么位置出问题&#xff0c;但是还想不清楚什么原因。 我先是在stc51单片机里面搞了串口&#xff0c;然后我想用串口重定向到printf做调试&#xff0c;…

深度学习实战70-数学教材智能问答MathGPT模型与题目latex的pdf生成技术

大家好,我是微学AI ,今天给大家介绍一下深度学习实战70-数学教材智能问答MathGPT模型与题目latex的pdf生成技术,本文利用MathGPT数学大模型实现的数学教材智能问答系统。该系统结合了自然语言处理和数学知识图谱,能够理解用户的数学问题,并提供准确的答案和解析,随时随地请…

Linux系统中的容器化技术

当谈到容器化技术时&#xff0c;Docker和Kubernetes是两个最为知名和广泛使用的工具。它们在Linux系统中发挥着重要的作用&#xff0c;为应用程序的部署、管理和扩展提供了强大的工具和框架。 首先&#xff0c;让我们来了解一下什么是容器化技术。容器化技术是一种虚拟化技术&a…

网络原理-TCP/IP(4)

TCP原理 滑动窗口 之前我们讲过了确认应答策略,对发送的每一个数据段,都要给一个ACK确认应答,收到ACK后再发送下一个数据段. 确认应答,超时重传,连接管理这样的特性都是为了保证可靠运输,但就是付出了传输效率(单位时间能传输数据的多少)的代价,因为确认应答机制导致了时间大…

基于 SpringBoot+Vue 的大学生租房系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

Linux 路由配置与使用

概念 路由信息用于指导数据包从源地址查找到目的地址传输路径的信息&#xff1b; 路由分类 根据路由信息的来源分为静态路由和动态路由 静态路由 由管理员手动配置的路由表项信息&#xff0c;根据路由形式的不同&#xff0c;静态路由又可细分为&#xff1a; 直连路由&#xf…

二叉树(1)

1 树概念及结构 1.1树的概念 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。 把它叫做树是因为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的。 有一个特殊的结点&a…

AI数字人训练数据集汇总

唇读&#xff08;Lip Reading&#xff09;&#xff0c;也称视觉语音识别&#xff08;Visual Speech Recognition&#xff09;&#xff0c;通过说话者口 型变化信息推断其所说的内容&#xff0c;旨在利用视觉信道信息补充听觉信道信息&#xff0c;在现实生活中有重要应用。例如&…

【文件上传WAF绕过】<?绕过、.htaccess木马、.php绕过

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【python】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏…

【MATLAB源码-第128期】基于matlab的雷达系统回波信号仿真,输出脉压,MTI,MTD等图像。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 ​雷达&#xff08;Radio Detection and Ranging&#xff09;是一种使用无线电波来探测和定位物体的系统。它的基本原理是发射无线电波&#xff0c;然后接收这些波从目标物体上反射回来的信号。通过分析这些反射波&#xff0…

Day 17------C语言收尾之链表的删除、位运算、预处理、宏定义

链表 空链表&#xff1a; 注意&#xff1a;函数不能返回局部变量的地址 操作&#xff1a; 1.创建空链表 2.头插 3.尾插 4.链表遍历 5.链表的长度 free&#xff1a;释放 删除&#xff1a; 头删 void popFront(struct Node *head) { //1.p指针变量指向首节点 //2.断…

人工智能深度学习发展历程-纪年录

前言 为了理解模型之间的改进关系、明确深度学习的发展目标、提高自身对模型的深度理解、贯彻爱与和平的理念。总之&#xff0c;我做了如下表格。 时间 重大突破 模型改进 详细信息 1847 SGD 随机梯度下降 1995 SVM 支持向量机 1982 RNN 循环神经网络&#xff0c;…

Kimera2: 面对真实路况中强大且具有准确尺度的语义SLAM

文章:Kimera2: Robust and Accurate Metric-Semantic SLAM in the Real World 作者:Marcus Abate , Yun Chang , Nathan Hughes , and Luca Carlone 编辑:点云PCL 欢迎各位加入知识星球,获取PDF论文,欢迎转发朋友圈。文章仅做学术分享,如有侵权联系删文。 公众号致力于…

基于STM32的DMA在外设数据交换中的应用案例

如何使用STM32的DMA在外设数据交换中实现高效的数据传输呢&#xff1f;下面&#xff0c;我将提供一个应用案例&#xff0c;涉及使用STM32的DMA在UART外设和内存之间进行数据传输的示例。 ✅作者简介&#xff1a;热爱科研的嵌入式开发者&#xff0c;修心和技术同步精进 ❤欢迎关…

Qt/C++音视频开发65-切换声卡/选择音频输出设备/播放到不同的声音设备/声卡下拉框

一、前言 近期收到一个用户需求&#xff0c;要求音视频组件能够切换声卡&#xff0c;首先要在vlc上实现&#xff0c;于是马不停蹄的研究起来&#xff0c;马上查阅对应vlc有没有自带的api接口&#xff0c;查看接口前&#xff0c;先打开vlc播放器&#xff0c;看下能不能切换&…

undo log 和 redo log的区别

undo log 和 redo log的区别 缓冲池&#xff08;Buffer Pool&#xff09;是MySQL用于存储数据页的内存区域&#xff0c;它用于减少对磁盘的读写操作&#xff0c;提高数据库的访问速度。在MySQL中&#xff0c;数据被分为多个固定大小的数据页&#xff08;通常为16KB&#xff09…

【Golang入门教程】如何使用Goland创建并运行项目

自然语言处理的发展 文章目录 自然语言处理的发展**前言**创建新项目编辑运行/调试配置编写并运行代码总结强烈推荐专栏集锦写在最后 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站: 人工…

算法篇之二分

二分算法简介 特点 最简单的一种算法&#xff0c;也是最恶心&#xff0c;细节最多&#xff0c;最容易写出死循环的算法时间复杂度O(logN) 如何学习 明白其中的算法原理&#xff0c;二分并不是只有数组有序的的时候使用&#xff0c;而是看是否具有二段性。模板 朴素的二分模…

JDK版本如何在IDEA中切换

JDK版本在IDEA中切换 一、项目结构设置 1.Platform——Settings 项目结构---SDKS 2.Project——SDK 3.Modules——SDK——Sources 4.Modules——SDK——Dependencies 二、设置--编译--字节码版本 Settings——Build,——Java Compiler

【linux】校招中的“熟悉linux操作系统”一般是指达到什么程度?

这样&#xff0c;你先在网上找一套完整openssh升级方案&#xff08;不是yum或apt的&#xff0c;要源码安装的&#xff09;&#xff0c;然后在虚拟机上反复安装测试&#xff0c;直到把他理解了、背下来。 面试的时候让你简单说说linux命令什么的&#xff0c;你就直接把这个方案…