对象的动态建立和释放

9.7 对象的动态建立和释放

  • 当对象是静态的,程序运行中,对象所占空间不能随时释放。例如函数中定义一个对象,只有该函数结束时,该对象才释放。
  • 为提高内存空间利用率,人们希望在用到对象时才建立对象,不用时就撤销它,释放其所占内存空间以供别的数据使用。可以用new运算符动态建立对象,用delete运算符撤销对象。
  • 若已定义一个Box类,可用以下方法建立一个对象。但用户还无法访问这个对象,因为该对象既无对象名,用户又不知其地址。这种对象称为无名对象,它确实存在,但它没有名字。
new Box;
//执行此语句时,系统开辟了一段内存空间,并在此内存空间中存放一个Box类对象,同时调用该类的构造函数,以使该对象初始化(如果已对构造函数赋予此功能的话)。
  • 用new运算符动态地分配内存后,将返回一个指向新对象的指针,即所分配的内存空间的起始地址。用户可获此地址,并通过该地址来访问这个对象。这样就需定义一个指向本类对象的指针变量来存放该地址。
Box *pt;				//定义一个指向Box类对象的指针变量pt
pt=new Box;				//在pt中存放了新建对象的起始地址

//在程序中可通过pt访问这个新建的对象
cout<<pt->height;		//输出该对象的height成员
cout<<pt->volume();		//调用该对象的volume函数,计算并输出体积

//可在执行new时,对新建立的对象进行初始化
Box *pt=new Box(12,15,18);		//定义指针变量和new建立新对象合并为一个语句,并指定初值
  • 调用对象既可通过对象名,也可通过指针。用new建立的动态对象一般是不用对象名的,是通过指针访问的,其主要应用于数据结构,如链表。访问链表中的结点,并不需要通过对象名,而是在上一个结点中存放下一个结点的地址,从而由上一个结点找到下一个结点,构成链表关系。
  • 在执行new运算时,若内存量不足,无法开辟所需内存空间,大多C++编译系统都使new返回一个0的指针值。只要检测返回值是否为0,就可判断分配内存是否成功。
  • 在不需要使用由new建立的对象时,可以用delete运算符予以释放。如果用一个指针变量pt先后指向不同的动态对象,应注意指针变量的当前指向,以免删错对象。
delete pt;				//释放pt指向的内存空间,此后程序不能再使用该对象。
//在执行delete运算符时,在释放内存空间之前,自动调用析构函数,完成有关善后清理工作。
### 动态分配与释放对象的概念 在编程中,动态分配释放对象是指程序运行期间通过特定机制为变量或对象分配内存并适时释放这些资源的过程。以下是关于C++Java两种语言中涉及的关键知识点。 --- #### **C++ 中的 `new` `delete`** 在C++中,`new` 运算符不仅负责动态分配内存,还会调用构造函数以初始化新创建的对象[^1]。相反,`delete` 负责清理对象(即调用析构函数),随后释放其占用的内存[^3]。这种特性使得 `new` `delete` 特别适合处理复杂的数据结构,尤其是那些需要执行额外初始化逻辑的情况。 ```cpp // 使用 new 创建对象实例 MyClass* obj = new MyClass(); // 使用 delete 销毁对象实例 delete obj; ``` 上述代码展示了如何利用 `new` 来创建一个名为 `MyClass` 的类的新实例,并使用 `delete` 删除该实例。值得注意的是,`new` 实际上调用了类的构造函数,而 `delete` 则会触发相应的析构函数[^2]。 此外,虽然通常认为 `new` 是在堆上分配内存,但实际上它的具体行为依赖于 `operator new` 的实现细节,可能涉及到不同的存储区域如自由存储区等[^4]。 --- #### **C++ 中的 `malloc` `free`** 另一方面,`malloc` 函数提供了一种更基础的方式来进行动态内存管理。它可以为任意类型的数据分配未初始化的原始字节块,并由程序员自行决定如何解释这块内存的内容。然而,当面对非内置数据类型的对象时,仅仅依靠 `malloc` `free` 并不足以满足需求,因为它们不会自动调用构造函数或者析构函数。 ```c++ // 使用 malloc 分配未经初始化的空间 void* ptr = malloc(sizeof(MyStruct)); // 手动初始化 (假设 MyStruct 需要显式的设置过程) if(ptr){ ((MyStruct*)ptr)->initialize(); } // 使用 free 释放空间 free(ptr); ``` 这里需要注意的是,如果尝试直接将 `malloc` 返回的结果当作已构建好的对象来使用,则可能会引发未定义的行为,除非手动完成了必要的初始化步骤。 另外值得一提的小技巧是,在某些情况下可以通过调整指针偏移量访问到 `malloc` 内部维护的一些元信息,但这属于非常规做法并不推荐实际应用当中采用[^5]。 --- #### **Java 中的 `new` 及垃圾回收机制** 相比之下,Java 提供了更为简洁统一的方法——通过关键字 `new` 即可完成对象的创建及其成员字段的默认赋值操作。更重要的一点在于 Java 自带了自动化垃圾收集器(Garbage Collector),开发者无需像 C/C++那样关心何时应该释放不再使用的对象;一旦某个对象变得不可达(即没有任何有效的引用指向它),GC 就会在适当时候将其从内存中清除掉。 ```java // 在 Java 中创建对象 MyClass obj = new MyClass(); // 不需要显示删除对象,交由 GC 处理 ``` 尽管如此,理解 JVM 如何管理工作线程、代数划分以及其他高级配置仍然有助于优化性能表现以及诊断潜在问题。 --- ### 总结对比 | 特性 | C++ (`new`, `delete`) | C (`malloc`, `free`) | Java (`new`, GC) | |---------------------|-------------------------------|--------------------------------|------------------------------| | 是否支持构造/析构 | 支持 | 不支持 | 构造支持 | | 存储位置 | 堆或其他 | 堆 | 堆 | | 用户责任 | 明确指定生命周期 | 完全掌控 | 主要是监控 | 以上表格总结了几种不同方式之间的差异之处。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值