不止于在栈上或堆上创建对象

11-本地方法栈和堆内存 11-本地方法栈和堆内存 一.本地方法栈 Nativemethodstack(本地方法栈):保存native方法进入区域的地址 对于一个运行中的Java程序而言,它还可能会用到一些跟本地方法相关的数据区。当某个线程调用一个本地方法时,它就进入了一个全新的并且不再受虚拟机限制的世界。本地方法可以通过本地方法接口来访问虚拟机的运行时数据区,但不止如此,它还可以做任何它想做的事情。 任何本地方法接口都会使用某种本地方法栈。当线程调用Java方法时,虚拟机会创建一个新的栈帧并压入Java栈。然而当它调用的是本地. 阅读详情

从真实开发经历来讲,只允许在栈上或者堆上创建对象的情况比较少,当然也有可能是我用C++开发的时间并不长。
  

Case 1 只在栈上创建

1、不考虑子类

  C++使用new来申请对象空间,要想只让其在栈上申请,要么让其在堆上无法申请,要么让其无法释放。
  所以,让new操作符或者delete操作符无法使用就可以了。

  class Base
  {
  public:
  protected:
  private:
      void* operator new(size_t t) {};
      void operator delete(void *) {};
  };
  int main()
  {
      Base* b = new Base;
      Base d;
      return 0;
  }

  此时new操作会报一个语法错误(IDE为vs2015)这里写图片描述,这里我们还可以看到编译器首先去检查的是操作符delete而不是new,所以只需要让操作符delete无法使用就足够了。
  
  在C++11以后的标准,我们还可以用delete(当然不是释放内存用的)关键字来实现。

  class Base
  {
  public:
       void operator delete(void *) = delete;
  protected:
  private:
  };
  int main()
  {
      Base* b = new Base;
      Base d;
      return 0;
  }

  此时操作符的编译错误是这里写图片描述。
  这里还有一个有意思的地方,可以看到两个new的声明是不一样的,而第二个还有一个+3重载,这个问题留着下回再讲:-)。

2、考虑子类

  由于基类已经无法在堆上申请所需空间,对于子类而言,由于其先要为基类申请空间。因此,子类必然不能在堆上创建对象。

Case 2 只在堆上申请

1、不考虑子类

  要想只在堆上申请,当然只有让其不能自动在栈上创建对象,所以可以让对象无法执行构造函数或者析构函数。

    class Base
  {
  public:
  protected:
  private:
      Base(){};
      ~Base(){};
  };
  int main()
  {
      Base b;
      return 0;
  }

  这时候,申明一个对象会报错这里写图片描述。注意这儿是先检查构造函数,而不是析构函数,跟new、delete可不一样。
  
  当然,此时也不能直接使用new操作符在堆上申请,所以我们取巧一下。

    class Base
  {
  public:
        static Base* create(size_t t = 1)
        {
            return new Base[t];
        }
        static void destroy(Base* b)
        {
            delete[] b;
        }
  protected:
  private:
        Base(){};
        ~Base(){};
  };
  int main()
  {
        Base* d = Base::create(10);
        Base::destroy(d);
        return 0;
  }

  在用new创建对象的时候最好用申请数组的方式,同时将长度参数默认设置为1,那样会更具有通用性一些。
  
  注意此时不能用delete关键字去禁用构造函数或者析构函数,因为在创建对象的时候,无论如何总要调用构造函数,在释放对象的时候,总要调用析构函数。

2、考虑子类

  如果是要让子类不受基类影响,可以把构造函数或者析构函数设为保护对象,对于子类而言,基类的保护成员是可以访问的。

    class Base
    {
    public:
        static Base* create(size_t t = 1)
        {
            return new Base[t];
        }
        static void destroy(Base* b)
        {
            delete[] b;
        }
    protected:
        ~Base(){};
    private:
    };

    class Derive :public Base
    {
    };

  int main()
  {
        Base* b = Base::create(10);
        Base::destroy(b);
        Derive* d = new Derive;
        delete d;
        Derive d2;
        return 0;
  }

  如果是要像基类一样只允许在堆上创建对象,那就得像基类一样再实现一遍create,destroy咯。

    class Base
    {
    public:
        static Base* create(size_t t = 1)
        {
            return new Base[t];
        }
        static void destroy(Base* b)
        {
            delete[] b;
        }
    protected:
        ~Base(){};
    private:
    };

    class Derive :public Base
    {
    public:
        static Derive* create(size_t t = 1)
        {
            return new Derive[t];
        }
        static void destroy(Derive* b)
        {
            delete[] b;
        }
    protected:
        ~Derive() {};
    };

  int main()
  {
        Derive* d = Derive::create(10);
        Derive::destroy(d);
        return 0;
  }
程序内存核心:堆与栈的区别、应用与问题排查指南 在计算机科学中,内存管理是程序运行的基石,其中堆和栈是两种核心的内存分配区域。栈采用自动管理机制,遵循后进先出原则,用于存储函数调用上下文和局部变量,分配速度快且无碎片,但容量有限。堆则支持动态内存分配,允许程序在运行时申请和释放大小可变的内存块,适合存储生命周期长或跨作用域的数据,但需要手动管理或依赖垃圾回收机制,易产生内存碎片和泄漏风险。理解堆栈原理对于优化程序性能、预防内存错误至关重要,尤其在处理缓冲区溢出、内存泄漏等常见安全与稳定性问题时。本文聚焦堆栈对比,结合JVM内存模型和堆缓冲区溢出等热词,解 阅读详情

相关推荐

【C++】如何用C++创建对象,理解作用域、堆栈、内存分配

而堆是不同的,一旦你在堆中创建一个对象,这个对象就会一直在那里,直到你做出释放它的决定。但是上述在栈上创建的对象和在堆上创建的对象还是有差异的,差异就是小标题1中的四点。即使一个没有类成员的类,就是啥也没有的类,你实例化它创建的对象也是至少要占用1个字节的内存的。正常的情况下,一个类中是有很多类成员的,所以我们需要内存存放类实例的这一堆变量的值。第二个差异是:如果你的对象太大,或者对象太多,你最好也是把你的对象创建在堆上。从上图可见,不管在栈上创建类实例还是在堆上创建类实例,都自动默认的调用了构造函数。

因为热爱所以坚持 978

C++实现一个只能在堆(栈)上生成对象的类

目录 只能在堆上生成对象的类 只能在栈上生成对象的类 在C++中,类的对象创建可以静态创建在栈区, 如A a;还可以动态创建在堆区,如A* ptr=new A;这两种方式是不同的, 具体来 静态建立一个类的对象,是由编译器为对象在栈空间中分配内存,是通过直接移动栈顶指针,挪出适当的空间,然后在这片内存空间上调用构造函数形成一个栈对象。使用这种方法,直接调用类的构造函数。 动态建立类对象...

爱上小公举 1998

易康eCognition9.0分类|规则集和机器学习的方法的面向对象的多尺度分割分类

基于易康eCognition9.0软件的规则集和机器学习的方法的面向对象的多尺度分割分类

weixin_46493028的博客 1万+

<c++基础(4)>堆和栈上对象创建的区别

在堆上和栈上创建对象的主要区别在于它们的内存管理方式和生命周期。

m0_56838271的博客 719

Tesseract-Ocr踩坑下载以及进行检验

1 OCR,即Optical Character Recognition:光学字符识别,是指通过扫描字符,然后通过其形状将其翻译成电子文本的过程。下载完成后进行解压找到这两个,然后复制到之前下载Tesseract-Ocr的tessdata文件下。可能会出现报错说chi下载的问题咱们不用管继续ok让它先下载完毕,后续会有下载chi的步骤。四、检验tesseract使用(将以下图片进行下载我这里将以下图片命名为3.png)我这里选的是2024年的版本如果下载不了;4 在安装的时候(找到下载的exe文件,双击)

m0_51428325的博客 1915

Spine换装系统深度优化:从局部换肤到动态合批的进阶之路

本文深入探讨了Spine换装系统的性能优化策略,从局部换肤到动态合批的进阶技术。通过分析传统方案的性能瓶颈,提出动态合批、GPU Instancing等高级优化方法,显著降低Draw Call和内存占用,提升游戏性能。适用于MMO和大型游戏开发,帮助技术美术和工程师突破大规模换装场景的性能限制。

vulkan6gpu的博客 554

栈上创建的对象和堆上创建的对象

1、对类的理解 1.1 类只是一个模板(Template),编译后不占用内存空间,所以在定义类时不能对成员变量进行初始化,因为没有地方存储数据。只有在创建对象以后才会给成员变量分配内存,这个时候就可以赋值了。 1.2 类可以理解为一种新的数据类型,该数据类型的名称是 Student。与 char、int、float 等基本数据类型不同的是,Student 是一种复杂数据类型,可以包含基本类型,而且还有很多基本类型中没有的特性。 2、栈上创建对象 如果创建的对象在栈上分配内存,需要使用&获取它的

m0_67877471的博客 1315

数字摄影与摄像中的图像信号处理器(ISP):流程与经典算法详解

图像信号处理器(Image Signal Processor, ISP)是现代数字成像系统(如智能手机、数码相机、网络摄像头等)中的核心组件,扮演着将图像传感器(如CMOS或CCD)捕获的原始光电信号转换为高质量、可供观看或进一步处理的数字图像的关键角色。在数字摄影和摄像的整个链路中,光线首先通过镜头(Lens)聚焦到图像传感器上,传感器将光信号转换为模拟电信号,随后经过模数转换(A/D转换)变为原始的数字图像信号。

qq_44682523的博客 3723

实现只在栈上创建对象的类

实现只在栈上创建对象的类 满足条件: 只能在栈上创建对象,即不能在堆上创建对象,因此将new的功能屏蔽掉即可,即屏蔽掉operator new和定位new表达式,注意:屏蔽了operator new,实际也将定位new屏蔽掉。 #include<iostream> using namespace std; class Stack{ public: static Stac...

Template Code 577

拖动无标题栏的cef3窗口

拖动嵌入了cef3的无标题栏win32窗口,本质上就是拖动子窗口移动父窗口这么个事情,这个在自己创建窗口的程序上处理非常简单,cef封装较多,想修改的完善点步骤较多。         cef所用版本3.2623。         就用cefclient来做测试工程,首先建议在cefclient_win.cc的RunMain函数中的app = new ClientAppRenderer();前面

loveyong1990的专栏 6160

GEE 案例:利用多源遥感数据计算RUSLE(Revised Universal Soil Loss Equation)土壤侵蚀

该数据集提供了全球范围内以250至500米的空间分辨率获取的多光谱图像数据,用于监测地表覆盖和变化。RUSLE模型的基本原理是通过考虑土壤侵蚀的主要驱动因素,来估计土壤侵蚀的速率。该数据集提供了全球范围内以10至60米的空间分辨率获取的多光谱图像数据,用于监测地表覆盖和变化。它对农业和土地资源管理者提供了一种评估和预测土壤侵蚀风险的工具,以制定适当的土壤保护措施和决策。2. soil(土壤)是来自OpenLandMap的土壤纹理分类数据,使用了USDA(美国农业部)土壤纹理分类系统。

此星光明博客 803

如何创建一个只能在堆上创建对象的类

C++创建对象有两种方式,一种是静态的创建对象,一种是动态的创建对象。 静态创建对象:在编译期间就已经为对象分配了内存空间编译器自动调用构造函数 动态创建对象:程序在运行期间才为对象开辟空间 如果我们想要只能在堆上创建对象,可能我们会想到在类里把构造函数声明成为私有的,这样一来我们就不能在外面直接定义对象,以为系统无法调用构造函数了。 但此时如果我们直接在类外面创建对象,那么在new 的时

persistence_s的博客 662

【异常】OpenClaw 项目 `fetch failed` 报错问题排查与解决方案Response interrupted: TypeError: fetch failed

针对无超时控制、异常兜底缺失导致的请求中断,封装标准化的安全请求工具,一次性解决超时控制、异常捕获、日志埋点三大问题,全项目替换原生。:将项目运行的 Node.js 版本升级至 18.x 及以上 LTS 版本,使用 Node.js 内置的稳定版。实现的网络请求环节,包括但不限于:第三方开放接口调用、内部服务接口通信、跨域资源请求、外部配置拉取等场景。:针对无法升级 Node.js 版本的存量环境,通过社区稳定兼容包替换原生。类型异常,直接造成业务请求响应中断。第二步:业务代码改造,替换原生。

奶爸的编程之路,也就一周冷个三天 367

C++ 构造函数-2 (初始化列表 - explicit - static 成员 - 只能在栈/堆上创建对象的类)

也就是说,在C++当中,这个位置不认为是初始化的地方:如上图,这个只是赋值。在这个位置才认为是 初始化。我们之前说过,当我们初始化一个成员的时候,如果是内置类型,不进行处理:但是也不是都不处理,如果这个内置类型,在类当中是定义给了值的:这个不是初始值,这个是 给 初始化列表的缺省值,也就是说,如果我们不对这个内置类型进行处理,那么这个x 就会被 赋 1 (缺省值)这个值,如果我们在初始化列表当中对这个x 进行了赋值,那么这个x 就是 在初始化列表当中初始化的值。

chihiro1122的博客 941

LLC 谐振转换器中为什么需要 ( L_m )(励磁电感)

在每个模态中,励磁电感 ( L_m )、谐振电感 ( L_r ) 和谐振电容 ( C_r ) 分别承担着储存和释放能量、维持谐振电流和电压波形的任务。Q1和Q2的交替导通确保了这些元件能够在不同的模态下实现能量的有效传输和谐振状态的维持。励磁电感 ( L_m ) 在这一过程中起着不可或缺的作用,确保了电路的高效运行和稳定性。

weixin_43199439的博客 3654

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

内存管理面试题

面试题一:设置一个不能被继承的类 思路: 子类继承父类的时候,子类的构造函数会自动调用父类的构造函数;子类的析构函数会自动调用父类的析构函数。所以只要将父类的构造函数和析构函数设置成私有的即可。(一旦设置成私有的,子类继承父类时,就会去调用父类函数和析构函数,从而导致编译器就会报错) 上述方法也存在一定的问题,将父类的构造函数和系统函数设置成私有的,如何实例化对象呢,又如何对不用的对象进行释放...

zhourong0511的博客 1390

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

那些奇葩的类的设计

盘点一些特殊的类的设计

知其然 知其所以然 762

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

C++内存管理:new与栈对象的核心差异与选择策略

在C++编程中,内存管理是影响程序性能和稳定性的核心概念。栈内存由编译器自动管理,分配释放速度快,生命周期与作用域绑定,适合局部变量和小型对象。堆内存则提供更大的灵活性和容量,允许运行时动态分配,但需要程序员手动管理,易引发内存泄漏和性能问题。从技术价值看,理解栈与堆的差异有助于编写高效、安全的代码,避免常见陷阱如悬空指针和内存泄漏。应用场景包括函数局部变量使用栈对象,而大型数据、多态对象和跨作用域存活的对象则需使用堆内存,并推荐结合智能指针实现自动管理。本文深入探讨了new与栈对象在生命周期、性能开销及使

weixin_30225755的博客 290

C++类实例化全解析:从栈对象到智能指针的五大方法与实践

在C++编程中,对象实例化是理解内存管理与程序性能的核心基础。其本质是将类蓝图转化为内存中的实体,涉及构造函数调用与资源分配。从原理层面,C++提供了栈与堆两种核心内存区域,分别对应自动与手动生命周期管理,这直接影响了程序的健壮性与效率。在技术价值上,不同的实例化方法(如直接定义、动态分配、placement new等)为开发者提供了从安全便捷到极致控制的不同选择,是现代C++工程实践中资源管理(RAII)与零开销抽象理念的具体体现。应用场景广泛覆盖了从局部变量、工厂模式到高性能内存池等需求。本文聚焦于C+

weixin_34162228的博客 280

[Java学习日记12】聊聊创建对象的三种方式

我是小耶 和你分享每一点知识 期待与你的下一次相遇。

2301_80329177的博客 348

关于一道C++笔试题的纠结,学计算机的伤不起啊

今天,一个在美国读计算机研究生的哥们问了我一道笔试题,来自某金融巨头,我看完后很纠结,表示学计算机的伤不啊,出题不带这么业余的。原题如下: defineclasssuchthatyoucanmakeobjectofthisclassonaheapbutnotonthestack. 大概意思是:定义一个类,只能在堆上创建对象,而不能在栈上创建对象。 题目...

weixin_30426065的博客 147

JVM-运行时数据区

运行时数据区是jvm中一个重要的组成部分,也是开发人员最关注的一个部分。java不同于C、C++,他们是开发人员掌控所有对象的生命周期,从创建到销毁都是由开发人员控制,而java则是自动内存管理,开发人员往往只需要创建对象即可,不需要关注对象是如何、何时被销毁的,不需要关注并不是它不需要销毁对象,而是交给了jvm自动进行垃圾回收,通常我们称之为GC。通常jvm管理的这部分内存可以划分为方法区、堆、虚拟机栈、程序计数器、本地方法栈。其中方法区和堆是线程共享区域,而虚拟机栈、程序计数器和本地方法栈

qq_43653951的博客 273

虚拟机知识夯实之路---内存区域与内存溢出异常

方式一:使用句柄,java堆分为句柄池和实例池,栈中的reference 存储对象的句柄地址,句柄中有两个指针,一个指向实例池的对象实例数据,另一个指向方法区中的对象类型数据。好处:栈中的reference存储稳定的句柄地址,当对象被移动的时候智慧改变句柄中的实例数据指针,reference本身不会被修改(垃圾收集时移动对象是非常普遍的)当对象是java数据的时候,需要记录数组的长度。栈中的reference存储堆中的对象地址,对象中包含到对象类型的指针和实例数据,指针指向方法区中的对象类型数据。

m0_56479934的博客 993

C++基础学习

类的实例化。//直接定义student my;//student就是类,my就是对象//在堆里面定义//C++中进行动态内存分配的一个例子。它在堆上创建了一个新的"student"类的对象,并将该对象的地址赋给指针变量"my"。这样可以让你使用超出对象创建函数或块的范围的对象。只需记得在使用完对象后使用"delete"关键字来正确释放内存,以防止内存泄漏访问和c一样student my;堆(heap)和栈(stack)是两种不同的内存分配方式,它们在内存中的位置和分配方式有所不同。

m0_72680791的博客 1315

C++对象内存布局(1)

基础类型 注意:在有的机器上double是4bytes。类的填充问题class A { int a; short b; int c; char d; }; class B { double a; int c; double d; int e; };类的size计算的基本原则是: 1. 类的单位是以块(Block)计算的,一块等于类中

blackerXHunter 532
上一篇: POJ 1008--Maya Calendar
下一篇: Kubernetes基于ovs构建docker集群
Hering_Linux
博客等级 码龄12年 0粉丝 49原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值