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.对象赋值