一、引用计数算法
引用计数是一种垃圾收集技术,用于管理计算机内存中的无用对象。当一个对象不再被引用时,这个对象就可以被系统安全地删除,以便回收其占用的内存空间。
引用计数的核心思想是跟踪每个对象的引用数。当一个对象被引用时,其引用数会增加;当一个引用不再引用该对象时,其引用数就会减少。当一个对象的引用数减少到0时,就意味着该对象不再被使用,可以被垃圾收集器回收。
引用计数具有简单、高效的优点,但也有一些局限性。例如,它无法处理循环引用的问题。如果两个对象互相引用,即使它们都不再被其他对象引用,它们的引用数也不会减少到0。
C++11开始使用智能指针管理资源,会自动管理引用计数的增加与减少。
二、VTK智能指针
VTK中创建一个对象可以用三种方法:
- 使用vtkObjectBase中的静态成员变量New(),使用Delete()方法析构;
- 使用智能指针vtkSmartPointer,无需手动调用Delete()方法减少引用计数
- 使用RAII模式的vtkNew;
在VTK中,对象都是被创建在堆上,必须Delete释放,否则会出现内存泄漏的情况。是由于VTK将vtkObjectBase类及其子类的构造函数都声明为受保护类型,不支持自行构造创建,这样就不能自动在函数栈上创建;使用智能指针创建对象,则无需手动调用Delete()方法减少引用计数,因为引用计数的增加与减少都是由智能指针自动完成的。VTK实现了便利的自动内存管理的概念,使用引用计数。与其他智能指针不同之处在于引用计数保留在VTK对象本身中,而不是智能指针类中。这样的好处在于:即使VTK对象作为原始指针传递,也可以增加引用计数。
2.1 vtkSmartPointer
VTK中的智能指针类为vtkSmartPointer,继承自vtkSmartPointerBase,可以看到是一个类模板。
使用时,如:
vtkSmartPointer<vtkBMPReader> reader = vtkSmartPointer<vtkBMPReader>::New();
vtkImageData* imageData = reader->GetOutput();
智能指针类型也可作为函数的返回值,如:
vtkSmartPointer<vtkImageData> MyFunction()
{
vtkSmartPointer<vtkImageData> myObject = vtkSmartPointer<vtkImageData>::New();
std::cout<<"MyFunction::myObject reference count = "<<myObject->GetReferenceCount()<<std::endl;
return myObject;
}
// 调用时
vtkSmartPointer<vtkImageData> MyImageData = MyFunction();
函数MyFunction()的返回值是通过复制的方式,将数据赋予调用的变量,因此改数据的引用计数保持不变,而且函数里的myObject不会被删除。
2.2 vtkNew
vtkNew是一个类模板,它在构造时使用T::New()分配并初始化其模板参数的实例。它假定在其生存期内拥有一个引用,并在销毁时调用T->Delete();可以看做是一个RAII的auto_ptr;
vtkNew被用于vtkSmartPointer的替代品,在简单环境中,可以使用vtkNew取代vtkSmartPointer; 功能和vtkSmartPointer一样,都是智能指针,不过更加轻量,推荐在局部变量使用,全局还是建议用vtkSmartPointer。
注意:vtkNew的赋值构造函数和拷贝构造函数都被禁用;
三、运行时类识别
VTK里在vtkObjectBase定义了获取对象类型的方法————GetClassName()和IsA()。getClassName()返回的是该对象类名的字符串(VTK用类名识别各个对象),如:
vtkSmartPointer<vtkBMPReader> reader = vtkSmartPointer<vtkBMPReader>::New();
const char* className = reader->GetClassName(); // 返回vtkBMPReader
IsA()方法用于测试某个对象是否为指定字符串的类型或其子类型,如:
if (reader->IsA("vtkImageReader")) {...}