stack对象与heap对象
从高地址到低地址,分别是stack,heap,static object,stack地址往下增长,heap地址往上增长。只要记住:stack栈顶地址反而小,就知道往下增长了。
禁止产生堆对象
1、产生堆对象使用new operator,可认为new operator有三个过程:
a、使用operator new操作符搜索可用的内存,分配一块内存;
b、在这块内存上,调用构造方法构造一个对象;
c、返回地址。
2、要禁止产生堆对象,可以声明类的operator new为private,禁止分配内存就好了。为了保持一致性,将operator delete也重载为private。
3、注意:new operator不能改变它的行为,operator new是可以重载的。
禁止产生栈对象
1、对于栈对象,栈顶指针挪出一块内存,调用构造方法直接构造对象,离开作用域,调用析构方法。
2、因此,要禁止产生栈对象。可以将构造方法或者析构方法声明为private。
3、将构造方法声明为private,那么问题来了,这将导致无法在类的外部使用new 创建堆对象,为什么?
因为new 产生堆对象也要在分配的内存上调用构造方法。private只能在类的内部使用,因此只能在类的内部使用new 创建堆对象,这就需要重新暴露一个接口,返回堆上创建的对象。也就是静态方法GetInstance。注意,这与单例模式不同,单例模式只使用一次new,返回的是同一个对象地址。而当前的情况是,每次调用静态方法,使用new,返回一个新的对象。
4、将构造方法声明为private,必须使用静态方法对外暴露产生的堆对象,同时构造方法有多个,为了禁止产生栈对象,每个都必须声明为private。有没有更好的办法呢?
5、将析构方法声明为private,毕竟析构方法就只有一个。析构方法为private,栈上对象调用构造方法,没有问题,离开作用域,试图调用析构方法,出错了。编译报错。使用new创建对象,没问题。
6、但是有新的问题了,这时候不能使用delete operator释放内存了。为什么?
考虑string* ps; delete ps产生如下的代码:
ps->~string();
operator delete(ps);
这就相当于,在外部使用private 析构方法了。编译当然出错。那该怎么办呢?
7、只能在类的内部使用delete,因此需要重新暴露一个接口Destroy(),Destroy调用delete。
8、将析构方法声明为private,还有一个问题。那就是,导致子类析构的时候无法调用父类的析构方法。怎么办?
将析构方法声明为protected。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理