如何限制对象只能建立在堆上或者栈上

C++每日面试之如何定义一个只能在堆上(栈上)生成对象的类? 原因:C++ 是静态绑定语言,编译器管理栈上对象的生命周期,编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性。若析构函数不可访问,则不能在栈上创建对象。 阅读详情

        原文地址:http://blog.youkuaiyun.com/szchtx/article/details/12000867

        在C++中,类的对象建立分为两种,一种是静态建立,如A a;另一种是动态建立,如A* ptr=new A;这两种方式是有区别的。

        静态建立一个类对象,是由编译器为对象在栈空间中分配内存,是通过直接移动栈顶指针,挪出适当的空间,然后在这片内存空间上调用构造函数形成一个栈对象。使用这种方法,直接调用类的构造函数。
        动态建立类对象,是使用new运算符将对象建立在堆空间中。这个过程分为两步,第一步是执行operator new()函数,在堆空间中搜索合适的内存并进行分配;第二步是调用构造函数构造对象,初始化这片内存空间。这种方法,间接调用类的构造函数。
        那么如何限制类对象只能在堆或者栈上建立呢?下面分别进行讨论。
1、只能建立在堆上
        类对象只能建立在堆上,就是不能静态建立类对象,即不能直接调用类的构造函数。
        容易想到将构造函数设为私有。在构造函数私有之后,无法在类外部调用构造函数来构造类对象,只能使用new运算符来建立对象。然而,前面已经说过,new运算符的执行过程分为两步,C++提供new运算符的重载,其实是只允许重载operator new()函数,而operator()函数用于分配内存,无法提供构造功能。因此,这种方法不可以。
        当对象建立在栈上面时,是由编译器分配内存空间的,调用构造函数来构造栈对象。当对象使用完后,编译器会调用析构函数来释放栈对象所占的空间。编译器管理了对象的整个生命周期。如果编译器无法调用类的析构函数,情况会是怎样的呢?比如,类的析构函数是私有的,编译器无法调用析构函数来释放内存。所以,编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性,其实不光是析构函数,只要是非静态的函数,编译器都会进行检查。如果类的析构函数是私有的,则编译器不会在栈空间上为类对象分配内存。
    因此,将析构函数设为私有,类对象就无法建立在栈上了。代码如下:
    class A  
    {  
    public:  
        A(){}  
        void destory(){delete this;}  
    private:  
        ~A(){}  
    };   
      试着使用A a;来建立对象,编译报错,提示析构函数无法访问。这样就只能使用new操作符来建立对象,构造函数是公有的,可以直接调用。类中必须提供一个destory函数,来进行内存空间的释放。类对象使用完成后,必须调用destory函数。
        上述方法的一个缺点就是,无法解决继承问题。如果A作为其它类的基类,则析构函数通常要设为virtual,然后在子类重写,以实现多态。因此析构函数不能设为private。还好C++提供了第三种访问控制,protected。将析构函数设为protected可以有效解决这个问题,类外无法访问protected成员,子类则可以访问。
        另一个问题是,类的使用很不方便,使用new建立对象,却使用destory函数释放对象,而不是使用delete。(使用delete会报错,因为delete对象的指针,会调用对象的析构函数,而析构函数类外不可访问)这种使用方式比较怪异。为了统一,可以将构造函数设为protected,然后提供一个public的static函数来完成构造,这样不使用new,而是使用一个函数来构造,使用一个函数来析构。代码如下,类似于单例模式:
    class A  
    {  
    protected:  
        A(){}  
        ~A(){}  
    public:  
        static A* create()  
        {  
            return new A();  
        }  
        void destory()  
        {  
            delete this;  
        }  
    };  
      这样,调用create()函数在堆上创建类A对象,调用destory()函数释放内存。
2、只能建立在栈上
   只有使用new运算符,对象才会建立在堆上,因此,只要禁用new运算符就可以实现类对象只能建立在栈上。将operator new()设为私有即可。代码如下:
  class A  
    {  
    private:  
        void* operator new(size_t t){}     // 注意函数的第一个参数和返回值都是固定的  
        void operator delete(void* ptr){} // 重载了new就需要重载delete  
    public:  
        A(){}  
        ~A(){}  
    };  
设计一个只能在堆上或栈上实例化的类 一道C++笔试题:设计一个只能在堆内存上实例化的类和一个只能在栈内存上实例化的类   只能在堆内存上实例化的类:将析构函数定义为private,在栈上不能自动调用析构函数,只能手动调用。也可以将构造函数定义为private,但这样需要手动写一个函数实现对象的构造。   只能在栈内存上实例化的类:将函数operator new和operator delete定义为private,这样使用new操作符创建对象时候,无法调用operator new,delete销毁对象也无法调用operator delete。 #include <iostream> using namespace s 立即下载

相关推荐

Cesium实战:如何在前端直接渲染TIFF影像(附完整代码与避坑指南)

本文详细介绍了如何在前端利用Cesium直接加载和渲染TIFF影像的完整技术方案。针对TIFF格式的地理影像数据,文章提供了从文件解析、坐标转换到像素处理与Cesium集成的全流程代码实现,并分享了性能优化与常见问题的避坑指南,帮助开发者高效实现三维地理可视化。

weixin_29290947的博客 314

C++实现一个只能在堆/栈上创建对象的类

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

imp0128的博客 1339

自动驾驶仿真 (三)—— 基于PreScan与Simulink的AEB系统仿真

自动驾驶仿真三—— 基于PreScan&Simulink的AEB系统仿真1. AEB自动紧急制动系统1. 1 TTC碰撞时间模型1. 2 C-NCAP法规部分术语与定义1. 3 主动安全ADAS系统试验项目2. AEB仿真分析建模2.1 搭建场景2.2 传感器建模2.3 添加AEB控制系统3. 典型工况仿真3.1 CCRs仿真测试3.1 CCRm仿真测试4. 参考学习的书目教材 博主前面的博文已经介绍了Prescan&Simulink基本的场景建模及仿真分析流程,《自动驾驶仿真 (二)——

zhudj08的博客 1万+

详解如何定义一个只能在堆上/栈上生成的类

相信有很多同学和我一样都遇到过这个问题,而且都无处下手,在网上搜答案可能也看不太明白,今天重新回顾了一下这个知识点,感觉掌握起来其实不难,相信你看完这篇博客 就能明白 1.如何定义一个只能在堆上生成的类      首先我们要在堆上定义一个对象的时候一定要用new ,比如A *a=new A; C++会先在堆上malloc一块内存,然后执行构造函数。      相信有些人看

hugang的博客 873

Python实战:ERA5风场数据区域提取与风向合成可视化全流程解析

本文详细解析了使用Python处理ERA5风场数据的完整流程,包括NC文件读取、特定区域数据提取、u/v分量合成风向风速的计算,以及利用Matplotlib进行风场时空演变可视化。内容涵盖从环境搭建、数据获取到高级绘图与性能优化的实战经验,为气象数据分析、风能评估及气候研究提供了一套清晰、可操作的技术指南。

swift5iosmith的博客 300

CH340驱动安装全攻略:从Windows到MacOS的避坑指南(2025最新版)

本文提供2025年最新版CH340驱动安装全攻略,涵盖Windows、MacOS和Linux三大操作系统。详细解析了驱动安装的核心原理、标准流程,并针对Windows设备管理器报错、MacOS系统安全限制等常见“坑点”提供了深度排错与解决方案,旨在帮助开发者快速稳定地完成USB转串口通信配置。

earth的博客 425

说的很清楚:限制对象只能建立在堆上或者栈上

在C++中,类的对象建立分为两种,一种是静态建立,如A a;另一种是动态建立,如A* ptr=new A;这两种方式是有区别的。         静态建立一个类对象,是由编译器为对象在栈空间中分配内存,是通过直接移动栈顶指针,挪出适当的空间,然后在这片内存空间上调用构造函数形成一个栈对象。使用这种方法,直接调用类的构造函数。         动态建立类对象,是使用new运算符将对象建立

xiongbixb2的专栏 369

ESP32-IDF HTTP服务器实战:从零搭建Web控制界面

本文详细介绍了如何在ESP32平台上使用ESP-IDF框架从零搭建HTTP服务器,并创建Web控制界面。内容涵盖环境配置、服务器基础设置、Web页面处理、GPIO控制接口实现及AJAX异步请求处理,帮助开发者快速掌握物联网设备Web控制开发。

efc123456的博客 1063

如何限制对象只能建立在堆上或者栈上(转载)

转载:http://blog.youkuaiyun.com/szchtx/article/details/12000867 在C++中,类的对象建立分为两种,一种是静态建立,如A a;另一种是动态建立,如A* ptr=new A;这两种方式是有区别的。 静态建立一个类对象,是由编译器为对象在栈空间中分配内存,是通过直接移动栈顶指针,挪出适当的空间,然后在这片内存空间上调用构造函数形成一个栈对象...

diaocuiguo2493的博客 111

手把手教你用YOLOv5和OpenCV实现DNF全自动刷图(含自动拾取与Boss战逻辑)

本文详细介绍了如何使用YOLOv5和OpenCV构建DNF全自动刷图系统,包括环境配置、游戏画面采集、目标检测、场景导航及操作控制等核心模块。通过实战案例,帮助开发者掌握游戏自动化技术,实现自动拾取与Boss战逻辑,提升游戏效率。

weixin_42628941的博客 446

23种设计模式-中介者(Mediator)设计模式

软考中级-软件设计师 中介者设计模式

片言可决讼,半纸能缚龙 1862

如何限制对象只能建立在堆上或者栈上【转载】

如何限制对象只能建立在堆上或者栈上 在C++中,类的对象建立分为两种,一种是静态建立,如A a;另一种是动态建立,如A* ptr=new A;这两种方式是有区别的。

小鱼的专栏 492

SAPIEN ManiSkill3 入门教程(一)

请注意,table.set_pose(pose) 设置的是演员在世界帧中的坐标系姿势。移除的实体可以再次添加到场景中,但已在场景中的实体则不能再次添加。显示器可以是物理的(如显示器),也可以是虚拟的(如 VNC)。我们可以通过 get_pose()、get_linear_velocity() 和 get_angular_velocity()获取演员的运动量(姿势、线速度、角速度)。现在,让我们创建一个斜坡。例如,您可能需要一个简单的碰撞形状来进行快速模拟,但却需要一个复杂的视觉形状来进行逼真的渲染。

机器人控制与仿真应用 3070

C++每日一问:如何限制类对象只能建立在堆上或者栈上?

在C++中,类的对象建立分为两种,一种是静态建立,如A a;另一种是动态建立,如A ptr=new A;这两种方式是有区别的。* 1)静态建立一个类对象,是由编译器为对象在栈空间中分配内存,是通过直接移动栈顶指针,挪出适当的空间,然后在这片内存空间上调用构造函数形成一个栈对象。使用这种方法,直接调用类的构造函数。 2)动态建立类对象,是使用new运算符将对象建立在堆空间中。这个过程分为两步,第一步是执行operator new()函数,在堆空间中搜索合适的内存并进行分配;第二步是调用构造函数构造对象,初始化

欧特GO 1395

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

上一篇: C++中堆和栈内存分配
下一篇: Android build system & Android.mk 规范
cbbbc
博客等级 码龄15年 609粉丝 37原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值