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

2024-02-01 22:52

本文主要是介绍【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;
}

三、运行结果

这篇关于【cmu15445c++入门】(5)C++ 包装类(管理资源的类)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/668732

相关文章

C++类和对象之初始化列表的使用方式

《C++类和对象之初始化列表的使用方式》:本文主要介绍C++类和对象之初始化列表的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C++初始化列表详解:性能优化与正确实践什么是初始化列表?初始化列表的三大核心作用1. 性能优化:避免不必要的赋值操作2. 强

C++迭代器失效的避坑指南

《C++迭代器失效的避坑指南》在C++中,迭代器(iterator)是一种类似指针的对象,用于遍历STL容器(如vector、list、map等),迭代器失效是指在对容器进行某些操作后... 目录1. 什么是迭代器失效?2. 哪些操作会导致迭代器失效?2.1 vector 的插入操作(push_back,

POI从入门到实战轻松完成EasyExcel使用及Excel导入导出功能

《POI从入门到实战轻松完成EasyExcel使用及Excel导入导出功能》ApachePOI是一个流行的Java库,用于处理MicrosoftOffice格式文件,提供丰富API来创建、读取和修改O... 目录前言:Apache POIEasyPoiEasyExcel一、EasyExcel1.1、核心特性

Python+PyQt5开发一个Windows电脑启动项管理神器

《Python+PyQt5开发一个Windows电脑启动项管理神器》:本文主要介绍如何使用PyQt5开发一款颜值与功能并存的Windows启动项管理工具,不仅能查看/删除现有启动项,还能智能添加新... 目录开篇:为什么我们需要启动项管理工具功能全景图核心技术解析1. Windows注册表操作2. 启动文件

Python中模块graphviz使用入门

《Python中模块graphviz使用入门》graphviz是一个用于创建和操作图形的Python库,本文主要介绍了Python中模块graphviz使用入门,具有一定的参考价值,感兴趣的可以了解一... 目录1.安装2. 基本用法2.1 输出图像格式2.2 图像style设置2.3 属性2.4 子图和聚

gradle第三方Jar包依赖统一管理方式

《gradle第三方Jar包依赖统一管理方式》:本文主要介绍gradle第三方Jar包依赖统一管理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录背景实现1.顶层模块build.gradle添加依赖管理插件2.顶层模块build.gradle添加所有管理依赖包

基于Python打造一个智能单词管理神器

《基于Python打造一个智能单词管理神器》这篇文章主要为大家详细介绍了如何使用Python打造一个智能单词管理神器,从查询到导出的一站式解决,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 项目概述:为什么需要这个工具2. 环境搭建与快速入门2.1 环境要求2.2 首次运行配置3. 核心功能使用指

C#如何调用C++库

《C#如何调用C++库》:本文主要介绍C#如何调用C++库方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录方法一:使用P/Invoke1. 导出C++函数2. 定义P/Invoke签名3. 调用C++函数方法二:使用C++/CLI作为桥接1. 创建C++/CL

C++如何通过Qt反射机制实现数据类序列化

《C++如何通过Qt反射机制实现数据类序列化》在C++工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作,所以本文就来聊聊C++如何通过Qt反射机制实现数据类序列化吧... 目录设计预期设计思路代码实现使用方法在 C++ 工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作。由于数据类

HTML5中的Microdata与历史记录管理详解

《HTML5中的Microdata与历史记录管理详解》Microdata作为HTML5新增的一个特性,它允许开发者在HTML文档中添加更多的语义信息,以便于搜索引擎和浏览器更好地理解页面内容,本文将探... 目录html5中的Mijscrodata与历史记录管理背景简介html5中的Microdata使用M