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

【C++ techniques】要求/禁止/判断—对象产生于堆中

  • 有时候我们想让某种对象具有“自杀”的能力,所以我们必须要求对象存在堆中,以便我们调用delete this;
  • 另一些时候,我们要求拥有某种确定性,保证某一些类型绝不会发生内存泄漏,原因是没有任何一个该类型的对象从堆中分配出来;堆空间非常宝贵,所以我们要对象全为栈对象,必须禁止对象产生于堆中。

要求对象产生于堆中(Heap-Based Objects)

  • 为限制对象产生于heap,我们需阻止clients不得使用new以外的方法产生对象;
  • non-heap objects会在其定义点自动构造,并在其寿命结束时自动析构,所以只需让那些被隐式调用的构造函数和析构函数不合法;
  • 比较好的方法是让destructor成为private,而constructors仍为public;
  • 如此一来,你可以导入一个pseudo destructor函数,用来调用真正的destructor。Clients则调用pseudo-destructor来销毁它们产生的对象。

例如,假设我们希望确保“表现无限精度”的数值对象只能诞生于heap之中:

class UPNumber
{
public:UPNumber();UPNumber(int initValue);UPNumber(double initValue);UPNumber(const UPNumber& rhs);private:~UPNumber();//dtor位于private内
};
//Clients于是应该这么写:
UPNumber n; //错误!(虽然合法,但当n的dtor被隐式调用,就不合法了)UPNumber* p = new UPNumber; //良好
...
delete p;	//错误!企图调用private destructor
p->destroy(); //良好
  • 只要限制destructor和constructors的运用,便可阻止non-heap objects的诞生,但是,它妨碍了继承和内含:
class UPNumber{...};	//将dtor或ctor声明为private
class NonNegativeUPNumber:public UPNumber{...};//错误!dtor或ctors无法通过编译class Asset
{
private:UPNumber value;		//错误!dtor或ctors无法通过编译...
};

解决:

  1. 令UPNumber的destructor成为protected(并仍保持其constructors为public),便可以解决继承问题;
  2. “必须内含UPNumber对象”之classes可以修改为“内含一个指针,指向UPNumer”对象:
class UPNumber{...};	//注意将dtor声明为protected
class NonNegativeUPNumber:public UPNumber{...}; //derived classes可以调用protected membersclass Asset
{
public:Asset(int initValue);~Asset();...
private:UPNumber* value;		
};Asset::Asset(int initvalue):value(new UPNumber(initValue))
{...
}Asset::~Asset()
{value->destroy();
}

判断某对象是否位于堆内

abstract mixin base class(抽象混合式基类):

  • abstract base class是一个不能被实例化的基类;
  • mixin class则提供一组定义完好的能力,能够与其派生类所可能提供的其他任何能力兼容。

我们可以形成一个所谓的抽象混合式基类,用来为派生类提供“判断某指针是否以operator new分配出来的能力:

class HeapTracked //mixin class;追踪并记录被operator new返回的指针
{
public:class MissingAddress{};virtual ~HeapTracked() = 0;static void* operator new(size_t size);//负责分配内存内存并将条目加入list内static void operator delete(void* ptr);//负责释放内存并从list身上移除条目bool isOnHeap() const; //决定某对象的地址是否在list内private:typedef const void* RawAddress;static list<RawAddress> addresses; //list记录所有由operator new返回的指针
};
//HeapTracked的完整实现内容:list<RawAddress> HeapTracked::addresses;HeapTracked::~HeapTracked{}void* HeapTracked::operator new(size_t size)
{void* memPtr = ::operator new(size);addresses.push_back(memPtr);return memPtr;
}void HeapTracked::operator delete(void* ptr)
{list<RawAddress>::iterator it  = find(addresses.begin(),addresses.end(),ptr);if(it != addresses.end()){address.erase(it);::operator delete(ptr);}else{throw MissingAddress();}
}bool HeapTracked::isOnHeap() const
{//取得一个指针,指向*this所占内存的起始处const void* rawAddress = dynamic_cast<const void*>(this);list<RawAddress>::iterator it = find(address.begin(),address.end(),rawAddress);return it != address.end();
}

禁止对象产生于堆中

一般而言有3种可能:

  1. 对象被直接实例化;
  2. 对象被实例化为派生类对象内的“基类”成分;
  3. 对象被内嵌于其他对象之中。

欲阻止clients直接将对象实例化于heap之中,你可以让client无法调用new:定义operator new,将其声明为private

如果不希望clients将UPNumber对象产生于堆内:

class UPNumber
{
private:static void* operator new(size_t size);static void operator delete(void* ptr);...
};

如果要禁止产生“UPNumer对象所组成的数组”,可以将operator new[]operator delete[]声明为private。

将operator new声明为private,往往也会妨碍UNumber对象被实例化为heap-based derived class objects的“base class成分”,因为operator new和operator delete会被继承,所以如果这些函数不在derived class声明为public,derived class继承的便是base(s)所声明的private版本:

class UPNumber{...};
class NonNegativeUPNumber:  //假设此class未声明operator newpublic UPNumber
{...
};NonNegativeUPNumber n1;				
static NonNegativeUPNumber n2;		
NonNegativeUPNumber* p = new NonNegativeUPNumber;//错误!企图调用private operator new

如果derived class声明一个属于自己的operator new(且为public),类似于,当我们企图分配一个“内含UPNumber对象”的对象,“UNPumber的operator new乃为private“不会带来什么影响:

class Asset
{
public:Asset(int initValue);...
private:UPNumber value;
};Asset* pa = new Asset(100); //没问题,调用的是//Asset::operator new或//::operator new而非UPNumber::operator new

我们曾经希望“如果一个UPNumber对象被构造于heap以外,那么就在UPNumber constructor内抛出异常”,这次我们希望“如果对象被产生于heap内的话,就抛出一个异常”。然而,就像没有任何根据移植性的做法可以判断某地址是否位于heap内一样,我们也没有根据移植性的做法可以判断它是否不在heap内。

相关文章:

【C++ techniques】要求/禁止/判断—对象产生于堆中

有时候我们想让某种对象具有“自杀”的能力&#xff0c;所以我们必须要求对象存在堆中&#xff0c;以便我们调用delete this&#xff1b;另一些时候&#xff0c;我们要求拥有某种确定性&#xff0c;保证某一些类型绝不会发生内存泄漏&#xff0c;原因是没有任何一个该类型的对象…...

吃鸡高手亲授:玩转绝地求生,分享顶级游戏干货!

绝地求生&#xff08;PUBG&#xff09;自上线以来&#xff0c;成为了全球热门游戏。作为吃鸡行家&#xff0c;我将分享一些独家技巧和干货&#xff0c;帮助您提高游戏战斗力&#xff0c;享受顶级游戏作战体验&#xff01; 首先&#xff0c;让我们谈一谈战斗力升级。想要在吃鸡游…...

Vue中如何进行自定义图表与可视化图形设计

Vue中如何进行自定义图表与可视化图形设计 在现代Web应用程序开发中&#xff0c;数据可视化图表和图形设计是至关重要的一部分。Vue.js是一个流行的JavaScript框架&#xff0c;它提供了强大的工具来构建交互性强大的用户界面。本文将探讨如何在Vue.js中进行自定义图表和可视化…...

学信息系统项目管理师第4版系列19_质量管理

1. 公差 1.1. 质量测量中公差是测量指标的可允许变动范围&#xff0c;而不是实际测量值与预期值的差 1.1.1. 【高22下选35】 1.2. 结果的的可接受范围 2. 控制界限 2.1. 统计意义上稳定的过程或过程绩效的普通偏差的边界 3. 3版 3.1. 质量控制新七工具 3.1.1. 【高19下…...

react库的基础学习

React介绍 React.js是前端三大新框架&#xff1a;Angular.js、React.js、Vue.js之一&#xff0c;这三大新框架的很多理念是相同的&#xff0c;但是也有各自的特点。 React起源于Facebook的内部项目&#xff0c;因为该公司对市场上所有 JavaScript MVC 框架&#xff0c;都不满…...

FFmpeg 基础模块:容器相关的 API 操作

目录 AVFormat 模块 AVFormat 前处理部分 AVFormat 读写处理部分 小结 思考 FFmpeg 目录中包含了 FFmpeg 库代码目录、构建工程目录、自测子系统目录等&#xff0c;具体内容如下&#xff1a; 现在你知道 FFmpeg 的源代码目录中都包含了哪些内容&#xff0c;在之后使用 FFm…...

SpringMVC+统一表现层返回值+异常处理器

一、统一表现层返回值 根据我们不同的处理方法&#xff0c;返回的数据格式都会不同&#xff0c;例如添加只返回true|false&#xff0c;删除同理&#xff0c;而查询却返回数据。 Result类 为此我们封装一个result类来用于表现层的返回。 public class Result {//描述统一格式…...

2023年地理信息系统与遥感专业就业前景与升学高校排名选择

活动地址&#xff1a;毕业季进击的技术er 地理信息系统&#xff08;GIS&#xff0c;Geographic Information System&#xff09;&#xff0c;又称“地理信息科学”&#xff08;Geographic Information Science&#xff09;&#xff0c;是一种具有信息系统空间专业形式的数据管理…...

第五章:最新版零基础学习 PYTHON 教程—Python 字符串操作指南(第二节 - Python 字符串—Python 字符串 len()的语法)

Python len() 函数返回字符串的长度。 目录 Python len() 语法 Python len() 示例 示例 1:带有元组和字符串的 Len() 函数...

ubuntu22.04使用共享文件设置

从ubuntu20.04开始&#xff0c;设置共享文件就很麻烦 第一步&#xff1a; 安装samba&#xff1a; sudo apt install samba第二步; 创建一个共享文件夹 我以桌面Desktop为例子 第三步&#xff1a; 设置密码&#xff1a; sudo smbpasswd -a ygc第四步&#xff1a; sudo vim …...

pycharm配置python3.8版本专门用于undecteded_chromedriver测试

pycharm配置python3.8版本专门用于undecteded_chromedriver测试 作者&#xff1a;虚坏叔叔 博客&#xff1a;https://pay.xuhss.com 早餐店不会开到晚上&#xff0c;想吃的人早就来了&#xff01;&#x1f604; 一、Pycharm及python环境的配置 1.安装python-3.8.7rc1-amd64.e…...

基于SpringBoot的民宿在线预定平台

目录 前言 一、技术栈 二、系统功能介绍 用户信息管理 民宿信息管理 民宿资讯管理 民宿分类管理 用户注册 民宿信息 我的订单 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实…...

CTFHUB SSRF

目录 web351 ​编辑 web352 web353 web354 sudo.cc 代表 127 web355 host长度 web356 web357 DNS 重定向 web358 bypass web359 mysql ssrf web360 web351 POST查看 flag.php即可 web352 <?php error_reporting(0); highlight_file(__FILE__); $url$_…...

FreeRTOS入门教程(队列详细使用示例)

文章目录 前言一、队列基本使用二、如何分辨数据源三、传输大块数据总结 前言 上篇文章我们已经讲解了队列的概念和队列相关的API函数&#xff0c;那么本篇文章的话就开始带大家来学习使用队列。 一、队列基本使用 这个例子将会创建三个任务&#xff0c;其中两个任务用来发送…...

【Kafka专题】Kafka收发消息核心参数详解

目录 前置知识课程内容一、从基础的客户端说起&#xff08;Java代码集成使用&#xff09;1.1 消息发送者源码示例1.2 消息消费者源码示例1.3 客户端使用小总结 *二、从客户端属性来梳理客户端工作机制*2.1 消费者分组消费机制2.2 生产者拦截器机制2.3 消息序列化机制2.4 消息分…...

matlab 使用激光雷达检测、分类和跟踪车辆

目录 1、算法概述2、加载数据3、地平面分割4、语义分割5、聚类和边界盒拟合6、可视化设置7、循环遍历数据8、面向跟踪的包围盒9、 总结10、 支持功能11、 参考</...

代码随想录训练营二刷第四十八天 | 139.单词拆分 背包问题总结

代码随想录训练营二刷第四十八天 | 139.单词拆分 背包问题总结 一、139.单词拆分 题目链接&#xff1a;https://leetcode.cn/problems/word-break/ 思路&#xff1a;单词拼字符串&#xff0c;完全背包。定义dp[i]&#xff0c;为true表示可以拆分为一或多个单词。可能会出现ab…...

【数据挖掘】2017年 Quiz 1-3 整理 带答案

目录 Quiz 1Quiz 2Quiz 3Quiz 1 Answer Problems 1-2 based on the following training set, where A , B , C A, B, C A,B,</...

吃鸡高手必备工具大揭秘!提高战斗力,分享干货,一站满足!

大家好&#xff01;你是否想提高吃鸡游戏的战斗力&#xff0c;分享顶级的游戏作战干货&#xff0c;方便进行吃鸡作图和查询装备皮肤库存&#xff1f;是否也担心被骗&#xff0c;希望查询游戏账号是否在黑名单上&#xff0c;或者查询失信人和VAC封禁情况&#xff1f;在这段视频中…...

集群化环境前置准备

目录 部署 1. 配置多台Linux虚拟机 1.1 首先&#xff0c;关机当前CentOS系统虚拟机&#xff08;可以使用root用户执行init 0来快速关 机&#xff09; 1.2 新建文件夹 1.3 克隆 1.4 同样的操作克隆出&#xff1a;node2和node3 1.5 开启node1&#xff0c;修改主机名为node1&…...

如何零门槛集成专业金融图表?从技术选型到上线的全流程攻略

如何零门槛集成专业金融图表&#xff1f;从技术选型到上线的全流程攻略 【免费下载链接】charting-library-examples Examples of Charting Library integrations with other libraries, frameworks and data transports 项目地址: https://gitcode.com/gh_mirrors/ch/charti…...

利用VMware虚拟机在本地模拟星图GPU平台环境测试MogFace-large

利用VMware虚拟机在本地模拟星图GPU平台环境测试MogFace-large 想试试最新的MogFace-large人脸检测模型&#xff0c;但手头没有现成的云GPU服务器&#xff1f;或者想先在本地环境里跑通流程&#xff0c;验证一下效果再上云&#xff1f;今天就来分享一个非常实用的方法&#xf…...

Termius vs SecureCRT:为什么这款内置FTP的SSH工具更适合中文用户?

Termius vs SecureCRT&#xff1a;为什么这款内置FTP的SSH工具更适合中文用户&#xff1f; 作为开发者&#xff0c;每天与服务器打交道是家常便饭。选择一款趁手的SSH工具&#xff0c;就像程序员挑选键盘一样重要——不仅要功能强大&#xff0c;更要符合个人使用习惯。对于中文…...

AvrLib-fork:面向AVR的C++14零开销硬件抽象库

1. 项目概述AvrLib-fork 是一个面向 AVR 微控制器平台的高度类型安全、现代 C&#xff08;C14 兼容&#xff09;嵌入式库&#xff0c;专为 PlatformIO 生态系统深度优化设计。它并非 Arduino Core 的简单封装&#xff0c;而是一套从底层硬件抽象出发、以零开销抽象&#xff08;…...

30分钟快速搭建企业级工作流系统:RuoYi-Flowable-Plus完整指南

30分钟快速搭建企业级工作流系统&#xff1a;RuoYi-Flowable-Plus完整指南 【免费下载链接】RuoYi-Flowable-Plus 本项目基于 RuoYi-Vue-Plus 进行二次开发扩展Flowable工作流功能&#xff0c;支持在线表单设计和丰富的工作流程设计能力。如果觉得这个项目不错&#xff0c;麻烦…...

JD-GUI完整使用指南:免费Java反编译工具的5大核心功能解析

JD-GUI完整使用指南&#xff1a;免费Java反编译工具的5大核心功能解析 【免费下载链接】jd-gui A standalone Java Decompiler GUI 项目地址: https://gitcode.com/gh_mirrors/jd/jd-gui Java开发者在日常工作中经常会遇到需要分析第三方库、调试未知代码或学习优秀项目…...

DeerFlow资源优化实践:控制Python执行环境内存占用方法

DeerFlow资源优化实践&#xff1a;控制Python执行环境内存占用方法 1. 认识DeerFlow&#xff1a;您的智能研究助手 DeerFlow是一个基于LangStack技术框架开发的深度研究开源项目&#xff0c;它就像是您的个人研究团队&#xff0c;能够帮您完成各种复杂的调研任务。这个工具整…...

【权威认证|Pydantic v2+Starlette v1.12+FastAPI 2.0深度兼容报告】:为什么你的async generator在/ai/chat接口里静默失败?

第一章&#xff1a;FastAPI 2.0 异步 AI 流式响应 避坑指南FastAPI 2.0 对异步流式响应&#xff08;StreamingResponse&#xff09;的底层行为进行了关键调整&#xff0c;尤其在事件循环绑定、响应体缓冲策略及客户端断连检测方面与 1.x 版本存在显著差异。若沿用旧版流式生成器…...

Hunyuan-MT-7B在学术论文翻译中的精准应用

Hunyuan-MT-7B在学术论文翻译中的精准应用 1. 学术翻译的痛点与挑战 学术论文翻译从来都不是简单的文字转换工作。想象一下&#xff0c;你辛辛苦苦写好的论文&#xff0c;里面充满了专业术语、复杂公式和严谨的参考文献&#xff0c;如果翻译时出现偏差&#xff0c;整个研究的…...

为什么头部金融科技公司已在2026 Q1全面切换Python AOT?——基于百万行代码仓库的构建耗时、镜像体积、安全扫描通过率真实数据复盘

第一章&#xff1a;Python 原生 AOT 编译方案 2026 对比评测报告Python 社区在 2025 年底迎来关键演进&#xff1a;CPython 官方正式将原生 AOT&#xff08;Ahead-of-Time&#xff09;编译能力纳入 3.14 开发主线&#xff0c;并以“Project Graviton”为代号推动落地。2026 年初…...