当前位置: 首页 > news >正文

C++Primer16.1.6节练习

练习16.28:

简易的shared_ptr代码如下

#include <iostream>
#include <vector>
#include <list>
using namespace std;//shared_ptr模板
template<typename T>class SharedPtr {friend SharedPtr<T>& MakeShared(T* t);
public://默认初始化SharedPtr() :ptr(nullptr), user(nullptr) { }//传入指向T的指针进行构造,防止隐式类型转换explicit SharedPtr(T* p = nullptr) :ptr(p), user(new size_t(1)) { }//拷贝构造SharedPtr(const SharedPtr& sp) :ptr(sp.ptr), user(sp.user){if (user != nullptr){++* user;}}//析构函数~SharedPtr();//赋值运算符SharedPtr& operator=(const SharedPtr&);//解引用运算符T& operator*() { return *ptr; }//常量版本T& operator*()const { return *ptr; }//返回指针T* get() { return ptr; }size_t use_count() { return *user; }bool unique(){if (use_count == 1){return true;}else{return false;}}private://指向T类型的指针T* ptr;//指向计数器的指针size_t* user;
};//定义make_shared
template<typename T>
SharedPtr<T> MakeShared(T* t)
{T* ptr = t;return SharedPtr<T>(ptr);
}//赋值运算符
template<typename T>
SharedPtr<T>& SharedPtr<T>::operator=(const SharedPtr& sp)
{if (this != sp){if (user == nullptr){--* user;if (*user == 0){delete ptr;delete user;}}ptr = sp.ptr;if (sp.user != nullptr){++* sp.user;}user = sp.user;}return *this;
}//析构函数
template<typename T>
SharedPtr<T>::~SharedPtr()
{if (user != nullptr){--* user;if (*user == 0){delete ptr;delete user;}}
}int main()
{SharedPtr<string>sp1(new string("hello"));SharedPtr<string>sp2 = MakeShared<string>(new string("world"));SharedPtr<int>sp3 = MakeShared<int>(new int(666));cout<<*sp1<<endl;cout << *sp2 << endl;cout << *sp3 << endl;system("pause");return 0;
}

结果如下:

 unique_ ptr代码如下:

#include <iostream>
#include <vector>
#include <list>
using namespace std;//shared_ptr模板
template<typename T>class UniquePtr {
public://默认初始化UniquePtr() :ptr(nullptr){ }//传入指向T的指针进行构造,防止隐式类型转换explicit UniquePtr(T* p) :ptr(p) { }//析构函数~UniquePtr();//不能拷贝,不能赋值运算符,定义为删除的函数UniquePtr(const UniquePtr&) = delete;UniquePtr& operator=(const UniquePtr&) = delete;//解引用运算符T& operator*() { return *ptr; }//常量版本T& operator*()const { return *ptr; }//u放弃对指针的控制权,返回指针,并将u置为空T* release();//释放u指向的对象,如果传入了内置指针,则使u指向这个对象,否则指控void reset();void reset(T* p);private://指向T类型的指针T* ptr;
};//u放弃对指针的控制权,返回指针,并将u置为空
template<typename T>
T* UniquePtr<T>::release()
{auto temp = ptr;if (ptr != nullptr){ptr == nullptr;}return temp;
}//释放u指向的对象,如果传入了内置指针,则使u指向这个对象,否则指控
template<typename T>
void UniquePtr<T>::reset()
{if (ptr != nullptr){delete ptr;ptr == nullptr;}
}template<typename T>
void UniquePtr<T>::reset(T* p)
{if (ptr != nullptr){delete ptr;}ptr = p;
}//析构函数
template<typename T>
UniquePtr<T>::~UniquePtr()
{if (ptr != nullptr){delete ptr;}
}int main()
{UniquePtr<string>sp1(new string("hello"));UniquePtr<string>sp2;UniquePtr<int>sp3(new int(666));cout << *sp1 << endl;cout << *sp3 << endl;cout << endl;sp2.reset(new string("world"));sp1.release();system("pause");return 0;
}

结果为:

 

练习16.29:

#include <iostream>
#include <vector>
#include <list>
using namespace std;//shared_ptr模板
template<typename T>class SharedPtr {friend SharedPtr<T>& MakeShared(T* t);
public://默认初始化SharedPtr() :ptr(nullptr), user(nullptr) { }//传入指向T的指针进行构造,防止隐式类型转换explicit SharedPtr(T* p = nullptr) :ptr(p), user(new size_t(1)) { }//拷贝构造SharedPtr(const SharedPtr& sp) :ptr(sp.ptr), user(sp.user){if (user != nullptr){++* user;}}//析构函数~SharedPtr();//赋值运算符SharedPtr& operator=(const SharedPtr&);//解引用运算符T& operator*() { return *ptr; }//常量版本T& operator*()const { return *ptr; }//返回指针T* get() { return ptr; }size_t use_count() { return *user; }bool unique(){if (use_count == 1){return true;}else{return false;}}private://指向T类型的指针T* ptr;//指向计数器的指针size_t* user;
};template<typename T, class ...Args>
SharedPtr<T>MakeShared(Args&&...args)
{return SharedPtr<T>(new T(std::forward<Args>(args)...));
}//赋值运算符
template<typename T>
SharedPtr<T>& SharedPtr<T>::operator=(const SharedPtr& sp)
{if (this != sp){if (user == nullptr){--* user;if (*user == 0){delete ptr;delete user;}}ptr = sp.ptr;if (sp.user != nullptr){++* sp.user;}user = sp.user;}return *this;
}//析构函数
template<typename T>
SharedPtr<T>::~SharedPtr()
{if (user != nullptr){--* user;if (*user == 0){delete ptr;delete user;}}
}//声明,类模板与函数模板的声明
template<typename>class BlobPtr;
template<typename>class Blob;
template<typename>class SharedPtr;
template<typename T>
bool operator==(const Blob<T>&, const Blob<T>&);
template<typename T>class Blob {//每个Blob实例将访问权限授予用相同类型实例化的BlobPtr和相等运算符friend class BlobPtr<T>;friend class SharedPtr<T>;//template<typename X>friend class BlobPtr<T>;friend bool operator==<T>(const Blob<T>&, const Blob<T>&);//template<typename X>friend bool operator==<T>(const Blob<T>&, const Blob<T>&);
public:typedef T value_type;typedef typename std::vector<T>::size_type size_type;Blob();Blob(std::initializer_list<T>il);//模板构造函数template<typename It>Blob(It b, It e);size_type size()const { return (*data).size(); }bool empty()const { return (*data).element_type(); }void push_back(const T& t) { (*data).push_back(t); }//移动版本void push_back(T&& t) { (*data).push_back(std::move(t)); }void pop_back();//元素访问T& back()const;T& operator[](size_type i);BlobPtr<T> begin() { return BlobPtr<T>(*this); }BlobPtr<T> end(){auto ret = BlobPtr<T>(*this, (*data).size());return ret;}T& front()const;private:SharedPtr<std::vector<T>>data;//data[i]无效,则抛出msgvoid check(size_type i, const std::string& msg)const;
};template<typename T>
T& Blob<T>::front()const
{check(0, "front on empty Blob");return data->front();
}//check
template<typename T>
void Blob<T>::check(size_type i, const std::string& msg)const
{if (i >= data->size()){throw std::out_of_range(msg);}
}//back
template<typename T>
T& Blob<T>::back()const
{check(0, "back on empty Blob");return data->back();
}//下标运算符
template<typename T>
T& Blob<T>::operator[](size_type i)
{check(i, "subscript out of range");return (*data)[i];
}//pop函数
template<typename T>
void Blob<T>::pop_back()
{check(0, "pop_back on empty Blob");data->pop_back();
}//构造函数
template<typename T>
Blob<T>::Blob() :data(MakeShared<std::vector<T>>()) { }//接受initializer_list的构造函数
template<typename T>
Blob<T>::Blob(std::initializer_list<T>il) : data(MakeShared<std::vector<T>>(il)) { }//若试图访问一个不存在的元素,BlobPtr抛出一个异常
template<typename T>class BlobPtr {
public:BlobPtr() :curr(0) { }BlobPtr(Blob<T>& a, size_t sz = 0) :wptr(a.data), curr(sz) { }T& operator*()const{auto p = check(curr, "dereference past end");return (*p)[curr];}//递增与递减BlobPtr& operator++();BlobPtr& operator--();BlobPtr& operator++(int);BlobPtr& operator--(int);T& deref() const;BlobPtr& incr();private:std::shared_ptr<std::vector<T>>check(std::size_t, const std::string&)const;std::weak_ptr<std::vector<T>>wptr;std::size_t curr;
};template<typename T>
T& BlobPtr<T>:: deref()const
{auto p = check(curr, "dereference past end");return (*p)[curr];
}template<typename T>
BlobPtr<T>& BlobPtr<T>::incr()
{//递增curr,判断curr位于合理位置,不合理位置不递增check(curr, "incrasement past end of BlobPtr");++curr;return *this;
}template<typename T>
BlobPtr<T>& BlobPtr<T>::operator++(int)
{BlobPtr ret = *this;++* this;return ret;
}template<typename T>
BlobPtr<T>& BlobPtr<T>::operator--(int)
{BlobPtr ret = *this;--* this;return ret;
}template<typename T>
BlobPtr<T>& BlobPtr<T>::operator++()
{check(curr, "increment past end of BlobPtr");++curr;return *this;
}template<typename T>
BlobPtr<T>& BlobPtr<T>::operator--()
{check(curr, "decrement past begin of BlobPtr");++curr;return *this;
}int main()
{Blob<int>b1 = { 1,2,3,4,5,6,7,8,9 };cout << b1.size() << endl;system("pause");return 0;
}

结果如下:

练习16.30:

见练习16.29

练习16.31:

shared_ptr是运行时绑定删除器,而unique_ptr则是编译时绑定删除器。unqiue_ptr有两个模板参数,一个是所管理的对象类型,另一个是删除器类型。因此,删除器类型是unique_ptr类型的一部分,在编译时就可知道,删除器可直接保存在unique_ptr对象中。通过这种方式,unique_ptr避免了间接调用删除器的运行时开销,而编译时还可以将自定义的删除器,如DebugDelete编译为内联形式 

相关文章:

C++Primer16.1.6节练习

练习16.28&#xff1a; 简易的shared_ptr代码如下 #include <iostream> #include <vector> #include <list> using namespace std;//shared_ptr模板 template<typename T>class SharedPtr {friend SharedPtr<T>& MakeShared(T* t); public…...

初尝并行编程

进程被分为后台进程和应用进程 大部分后台进程在系统开始运行时被操作系统启动&#xff0c;完成操作系统的基础服务功能。大部分应用进程由用户启动&#xff0c;完成用户所需的具体应用功能 进程由程序段、数据段、进程控制块三部分组成 程序段也被称为是代码段&#xff0c;…...

keepalived学习记录:对其vip漂移过程采用gdb跟踪

对其vip漂移过程采用gdb跟踪keepalived工具主要功能产生vip漂移过程两种情况gdb调试常用命令gdb调试时打到的函数栈&#xff08;供学习参考&#xff09;函数栈的图是本人理解下画的&#xff0c;不对请多指正 keepalived主要有三个进程&#xff0c;父进程是core进程&#xff0c;…...

51单片机串口通讯原理及程序源码-----day8

51单片机串口通讯原理及程序源码-----day8 1.定义单片机为TTL电平&#xff1a;高 5V 低 0V RS232电平&#xff1a; 计算机的串口高 -12V 低12V 所以计算机与单片机之间通讯时需要加电平转换芯片CH340T 、 MAX232。 2.通信分类&#xff1a; &#xff08;1&#xff09;并行通信通…...

mongodb入门到使用(下)

mongodb中常用命令操作一、用户操作二、创建用户三、数据库操作基本操作四、扩展操作五、集合操作一、用户操作 在mongo中使用mongodb都需要在admin数据库中操作。然后在使用下面的命令 use admin二、创建用户 db.createUser({"user":"imooc", #用户名&q…...

云HIS系统源码 医院his源码 云his源码

大型医院his系统源码 SaaS运维平台多医院入驻强大的电子病历完整文档 &#xff0c;有演示 一、系统概述&#xff1a; 基层卫生健康云是一款满足基层医疗机构各类业务需要的健康云产品。该产品能帮助基层医疗机构完成日常各类业务&#xff0c;提供病患挂号支持、病患问诊、电子…...

朴素贝叶斯法学习笔记

频率派和贝叶斯派 频率派认为可以通过大量实验&#xff0c;从样本推断总体。比如假定总体服从均值为μ\muμ&#xff0c;方差为σ\sigmaσ的分布。根据中心极限定理&#xff0c;是可以通过抽样估算总体的参数的&#xff0c;而且抽样次数越多&#xff0c;对总体的估计就越准确。…...

vscode与C++安装与使用【不好用来骂我】

网上教程很多&#xff0c;但是都不太好用&#xff0c;这是我垃圾堆里淘金淘出来的教程&#xff1a; 安装软件 安装 Visual Studio Code: 你需要下载并安装 Visual Studio Code&#xff0c;可以在官网下载 https://code.visualstudio.com/download。 安装 C 扩展: 在 Visual S…...

C++11使用多线程(线程池)计算相似度实现性能优化

需求&#xff1a;图像识别中&#xff0c;注册的样本多了会影响计算速度&#xff0c;成为性能瓶颈&#xff0c;其中一个优化方法就是使用多线程。例如&#xff0c;注册了了3000个特征&#xff0c;每个特征4096个float。可以把3000个特征比对放到4个线程中进行计算&#xff0c;然…...

【测绘程序设计】——平面坐标转换

测绘工程中经常遇到平面坐标转换——比如,北京54(或西安80)平面坐标转换成CGCS2000平面坐标、工程独立坐标系平面坐标转换成CGCS2000平面坐标等,常用转换模型包括:①三参数法(2平移+1旋转);②四参数法(赫尔默特法,2平移+1旋转+1尺度);③六参数法(仿射变换法,2平移…...

五子棋的设计与实现

术&#xff1a;Java等摘要&#xff1a;五子棋是一种两人对弈的纯策略型棋类游戏&#xff0c;非常容易上手&#xff0c;老少皆宜。为了更好的推广五子棋&#xff0c;研究简单的人工智能方式&#xff0c;运用Java开发五子棋游戏。主要包含了人机对战&#xff0c;棋盘初始化&#…...

大数据项目软硬件选择

目录 一.技术选型 二.系统数据流程设计 三.框架版本选型 如何选择Apache/CDH/HDP版本...

redis数据结构的适用场景分析

1、String 类型的内存空间消耗问题&#xff0c;以及选择节省内存开销的数据类型的解决方案。 为什么 String 类型内存开销大&#xff1f; 图片 ID 和图片存储对象 ID 都是 10 位数&#xff0c;我们可以用两个 8 字节的 Long 类型表示这两个 ID。因为 8 字节的 Long 类型最大可以…...

同步、异步、全双工、半双工的区别

1、通讯 1.1 并行通讯 定义&#xff1a;一条信息的各位数据被同时传送的通讯方式称为并行通讯&#xff1b; 特点&#xff1a; 各个数据位同时发送&#xff0c;传送速度快、效率高&#xff0c;但有多少数据位就需要多少根数据线&#xff0c;因此传送成本高&#xff0c;并且只…...

ClickHouse 与 Amazon S3 结合?一起来探索其中奥秘

目录ClickHouse 简介ClickHouse 与对象存储ClickHouse 与 S3 结合的三种方法示例参考架构小结参考资料ClickHouse 简介ClickHouse 是一种快速的、开源的、用于联机分析&#xff08;OLAP&#xff09;的列式数据库管理系统&#xff08;DBMS&#xff09;&#xff0c;由俄罗斯的Yan…...

【Spark分布式内存计算框架——Structured Streaming】1. Structured Streaming 概述

前言 Apache Spark在2016年的时候启动了Structured Streaming项目&#xff0c;一个基于Spark SQL的全新流计算引擎Structured Streaming&#xff0c;让用户像编写批处理程序一样简单地编写高性能的流处理程序。 Structured Streaming并不是对Spark Streaming的简单改进&#xf…...

【Windows】【Linux】---- Java证书导入

问题&#xff1a; PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 无法找到请求目标的有效证书路径 一、Windows—java证书导入 1、下载证书到本地&#xff08;以下…...

【Linux学习】菜鸟入门——gcc与g++简要使用

一、gcc/g gcc/g是编译器&#xff0c;gcc是GCC(GUN Compiler Collection&#xff0c;GUN编译器集合)中的C编译器&#xff1b;g是GCC中的C编译器。使用g编译文件时会自动链接STL标准库&#xff0c;而gcc不会自动链接STL标准库。下面简单介绍一下Linux环境下&#xff08;Windows差…...

Cadence Allegro 导出Bill of Material Report详解

⏪《上一篇》   🏡《总目录》   ⏩《下一篇》 目录 1,概述2,Assigned Functions Report作用3,Assigned Functions Report示例4,Assigned Functions Report导出方法4.1,方法14.2,方法2B站关注“硬小二”浏览更多演示视频...

localStorage线上问题的思考

一、背景&#xff1a; localStorage作为HTML5 Web Storage的API之一&#xff0c;使用标准的键值对&#xff08;Key-Value,简称KV&#xff09;数据类型主要作用是本地存储。本地存储是指将数据按照键值对的方式保存在客户端计算机中&#xff0c;直到用户或者脚本主动清除数据&a…...

什么是DNS域名解析

什么是DNS域名解析&#xff1f;因特网上作为域名和IP地址相互映射的一个分布式数据库&#xff0c;能够使用户更方便的访问互联网&#xff0c;而不用去记住能够被机器直接读取的IP数串。通过主机名&#xff0c;得到该主机名对应的IP地址的过程叫做域名解析。正向解析&#xff1a…...

Cadence Allegro 导出Assigned Functions Report详解

⏪《上一篇》   🏡《总目录》   ⏩《下一篇》 目录 1,概述2,Assigned Functions Report作用3,Assigned Functions Report示例4,Assigned Functions Report导出方法4.1,方法14.2,方法2B站关注“硬小二”浏览更多演示视频...

Python中Opencv和PIL.Image读取图片的差异对比

近日&#xff0c;在进行深度学习进行推理的时候&#xff0c;发现不管怎么样都得不出正确的结果&#xff0c;再仔细和正确的代码进行对比了后发现原来是Python中不同的库读取的图片数组是有差异的。 image np.array(Image.open(image_file).convert(RGB)) image cv2.imread(…...

win10 WSL2 使用Ubuntu配置与安装教程

Win10 22H2ubuntu 22.04ROS2 文章目录一、什么是WSL2二、Win10 系统配置2.1 更新Windows版本2.2 Win10系统启用两个功能2.3 Win10开启BIOS/CPU开启虚拟化(VT)&#xff08;很关键&#xff09;2.4 下载并安装wsl_update_x64.msi2.5 PowerShell安装组件三、PowerShell安装Ubuntu3.…...

LeetCode每日一题(28. Find the Index of the First Occurrence in a String)

Given two strings needle and haystack, return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. Example 1: Input: haystack “sadbutsad”, needle “sad” Output: 0 Explanation: “sad” occurs at index 0 and…...

Android 圆弧形 SeekBar

效果预览package com.gcssloop.widget;import android.annotation.SuppressLint;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Matrix;import android.graph…...

java 字典

java 字典 数据结构总览 Map Map 描述的是一种映射关系&#xff0c;一个 key 对应一个 value&#xff0c;可以添加&#xff0c;删除&#xff0c;修改和获取 key/value&#xff0c;util 提供了多种 Map HashMap: hash 表实现的 map&#xff0c;插入删除查找性能都是 O(1)&…...

【企业服务器LNMP环境搭建】mysql安装

MySQL安装步骤&#xff1a; 1、相关说明 1.1、编译参数的说明 -DCMAKE_INSTALL_PREFIX安装到的软件目录-DMYSQL_DATADIR数据文件存储的路径-DSYSCONFDIR配置文件路径 (my.cnf)-DENABLED_LOCAL_INFILE1使用localmysql客户端的配置-DWITH_PARTITION_STORAGE_ENGINE使mysql支持…...

vue自定义指令以及angular自定义指令(以禁止输入空格为例)

哈喽&#xff0c;小伙伴们&#xff0c;大家好啊&#xff0c;最近要实现一个vue自定义指令&#xff0c;就是让input输入框禁止输入空格建立一个directives的指令文件&#xff0c;里面专门用来建立各个指令的官方文档&#xff1a;自定义指令 | Vue.js (vuejs.org)我们都知道vue中…...

异常 复习

异常复习 异常(广义)&#xff1a;泛指程序中一切不正常的情况 错误&#xff1a;例如内存不够用,程序是无法解决的 异常(狭义)&#xff1a;程序在运行中出现问题,但是可以通过异常处理机制处理,程序可以继续向后执行 异常体系 Throwable类有两个直接子类&#xff1a;Excepti…...

网站信息 订阅如何做/快速网站排名优化

这里的this 指的是你的方法或成员或操作火灾的这个类&#xff0c;this在这里的作用是说明,你必须在该类里面来实现ActionListener里面的actionPerformed方法,其实(Object t);这里的参数的意思是&#xff0c;这个t是哪个类的对象&#xff0c;那么那个类就负责来实现接口的方法&a…...

宝安网站制作哪家强/系统优化软件哪个最好的

网络运营商需要5G带来的敏捷网络的优势&#xff0c;根据Brocade执行官的看法&#xff0c;业界已经等不及正式的5G标准的诞生了。 Brocade近日发布了旨在加速向5G过渡的新产品&#xff0c;但这是在正式的5G标准问世之前不成熟的厂商如Brocade推出的5G技术吗&#xff1f;它的未来…...

拖拽建站平台/什么平台可以免费打广告

七、招生问答1、上课时间怎么安排&#xff1f;答&#xff1a;因为我们是一对一上课。所以&#xff0c;上课时间是由您自己来安排&#xff0c;您什么有空&#xff0c;就什么时候来学习。2、我很笨&#xff0c;学不会怎么办&#xff1f;答&#xff1a;其实人与人之间&#xff0c;…...

做企业官网需要多少钱/seo营销技巧培训班

小练习&#xff0c;小练习哈&#xff0c;直接上代码&#xff0c;上课上的太无聊了&#xff0c;来玩一玩vue来了~ <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"…...

网站开发学费/济南做网站比较好的公司

背景&#xff1a;不用说&#xff0c;学习C的你&#xff0c;一定知道这是个词……至于难不难懂&#xff0c;就看你的理解能力了&#xff0c;我理解也是费劲千辛万苦啊&#xff0c;成员函数的重载、覆盖&#xff08;override&#xff09;、隐藏、virtual 很容易混淆&#xff0c;C…...

网站建设的素材/seo网站关键词排名优化公司

我思考了一下上一个程序为什么会失败&#xff0c;可能还是太远了&#xff0c;所以这次弄近一点。把5000米改成1000米吧。。。其他的还是不变 function的持续不变&#xff0c;在这里就不重复写了&#xff0c;具体参照上一篇博客 主函数&#xff1a;关于亮点1 % clc;close all;cl…...