随笔 - 576  文章 - 0  评论 - 62  阅读 - 219万

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。

posted on   Andy Niu  阅读(940)  评论(0编辑  收藏  举报
编辑推荐:
· 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编程运行原理
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示