OOP学习笔记七:无用单元

1.无用单元收集问题

1.1无用单元和悬挂引用:

无用单元就是一块存储区,在程序中不可对其引用(无用对象);悬挂引用就是当指针指向的对象被删除,但程序员仍然认为被删除的内存的地址仍然有效的时候(无用指针)。一般多个指针持有同一个地址,即指针别名,通常会导致悬挂引用。

1.2语言设计:

C++是一种基于值得语言(C也是)。也就是说一切(对象和基本类型)皆为值。每个对象都是有着真实的内存存储空间。

1.3C++何时产生无用单元

(1)从函数退出时,在函数内部创建的所有局部变量(包括对象)以及按值传递的所有参数都不可访问。

(2)从块退出时,在块内部声明的所有局部变量(包括对象)都不可访问。

(3)任何复杂表达式包含的临时变量,在不需要时必须全部销毁,否则将成为无用单元。

(4)任何动态分配的对象,在不需要的时候必须由程序员显式地销毁。

(5)赋值和复制时也会产生无用单元。

 

2.C++中的无用单元收集

如果在某个作用域中声明了某个类的对象,在退出作用域时,由语言(编译器)自动为在该作用域中创建的自动(基于栈)对象调用析构函数。一旦析构完成,对象将彻底消失。

对于动态创建的对象(在堆上)可用delete操作符删除。

TPerson *p;
p = new TPerson(“12-25-95”);
//...
delete p;

这里delete删除指针的时候实际上是通过该对象调用该对象所属类的析构函数。

一般而言,在对象即将被销毁时,包含在该对象中的所有对象的析构函数将被递归地调用,直至所有被包含的对象都被销毁。这只适合用于按值包含在其他对象中的对象。

如果某对象包含指向其他对象的指针,则需要程序员手动销毁。

3.对象的标识

int main(){
 TPerson person0("Albert Einstein",0,0,"12-11-1879");
 TPerson person1("12-11-1879");
 TPerson* person2 = new TPerson("10-11-95");
 TPerson* person3 = new TPerson("6-27-87");
 TPerson* person4 = 0;
 TPerson* person5 = 0;
 
 person1.SetName("Albert Einstein");
 person2->SetName("Foo Bar");
 person4 =person3;
 return(0);
 }

如上所示,person0和person1分别采用不同的构造函数构造,这两个对象的名次就是person0和person1;

但是person2并不是对象的真正名称,它表示内存中另外创建的一个无名称的对象。person3同理。但是可以通过*person2来间接的表示该对象名。

如果执行如下操作

person5 = person3;

则使得person5指向了person指向的对象,此时person3,4,5共享了对象。

如果执行如下操作

delete person4;
person4 = 0;

则person3,4,5所指向的对象被删除了,person4被删除,person3和person5都变成了悬挂引用。

接着如果继续执行如下操作

person4 = &person1;
person3 =person2;
person5 = 0;

此时创建了无用单元,原来最初由person3,person4,person5所表示的对象已经无法找到。该对象仍然在运行程序中占用内存(如果是迭代过程中始终创建那么最终就会导致溢出而程序崩溃)

4.对象复制

在许多不同的情况都需要复制对象,比如按值传递(和按值返回)参数给函数时,就需要制作对象的副本。当函数被调用时,复制操作由语言(编译器)发起,这是一个隐式进行的操作。

5.对象赋值

你可能感兴趣的:(C++)