摘要: 在调用某些FDO的函数的时候,需要申请内存,并且这些内存应该在适当的时机释放掉,避免发生内存泄露。FDO用引用计数的方式来实现管理对象的生命周期,这样每个对象都维护着一个引用计数,当这个对象的引用计数变为0时,这个对象就会被释放。因此,FDO中每个类都是从Fd...
在调用某些FDO的函数的时候,需要申请内存,并且这些内存应该在适当的时机释放掉,避免发生内存泄露。FDO用引用计数的方式来实现管理对象的生命周期,这样每个对象都维护着一个引用计数,当这个对象的引用计数变为0时,这个对象就会被释放。因此,FDO中每个类都是从FdoIDisposable类继承而来的,FdoIDisposable定义了Release()和AddRef()方法。调用方法Release()会将当前对象的引用计数减1,然后判该对象的引用计数是否位0,如果是那么就释放这个对象;相应的方法AddRef()会将当前对象的引用计数加1。并且为了防止用于调用操作符delete释放一个对象,在FDO中所有类的析构函数都是被保护的,释放对象只能通过调用Release()方法。
一·FDO中内存管理相关的宏
FDO预定义了两个宏用来简化对象的创建和释放。
1. FDO_SAFE_RELEASE (ptr)*
若“ptr”为非空指针,那么FDO_SAFE_RELEASE会调用“ptr”指向的对象的Release()方法,然后把指向该对象的指针赋值为NULL。该宏定义的实现为:
<pre class="brush:py"> define FDO_SAFE_RELEASE(x) {if (x) (x)->Release(); (x) = NULL;} </pre>
该宏的使用方式如下所示: FdoFeatureClass* pBase = myClass->GetBaseClass(); ... FDO_SAFE_RELEASE(pBase);
2.FDO_SAFE_ADDREF (ptr)*
若“ptr”为非空指针,那么FDO_SAFE_ADDREF会调用“ptr”指向的对象的AddRef()方法。这一宏定义的实现为:
define FDO_SAFE_ADDREF(x) ((x != NULL) ? (x)->AddRef(), (x): (NULL))
二·FDO的智能指针FdoPtr
用来协助内存管理的智能指针FdoPtr,是一个C++的模板类,其模板参数必须是继承自FdoIDisposable的类。该指针可以封装FDO对象,然后,在FdoPtr出作用域时对象可以自动释放。下面是使用FdoPtr的一个例子:
FdoPtr<FdoFeatureClass> pBase = myClass->GetBaseClass();
...
以上的这段代码不需要对FDO_SAFE_RELEASE进行调用,因为在Fdoptr被销毁前,FdoFeatureClass对象的Release()方法会被pBase调用。
当我们想要用FdoPtr来调用FDO_SAFE_RELEASE时,首先我们要得到FdoPtr封装的指向对象的指针,然后再把该指向对象的指针传入到FDO_SAFE_RELEASE。用户可以用FdoPtr来自定义类,自然,这些类需要从FdoIDisposable继承,且要实现Dispose()的方法。若给一个非智能指针用FDO方法返回的指针赋值,那么就应该把这个非智能指针再给一个FdoPtr赋值,例如:
FdoLineString* p = gf.CreateLineString(...);
FdoPtr <FdoLineStringp2 = FDO_SAFE_ADDREF(p);
智能指针给内存管理带来很大的便利,但不当的使用也会带来一定的问题,其中一个较为常见的问题就是链式调用,链式调用将导致返回的指针无法释放。假设指向类FdoClassDefinition实例的一个指针为pclassDef,那么下面的代码将会导致两处内存的泄露。
psz = pclassDef ->GetProperties()->GetItem(0)-GetName());
正确的用法为:
FdoPropertyDefinitionCollection* pprops = pclassDef -GetProperties();
FdoPropertyDefinition* ppropDef = pprops-GetItem(0);
psz = propDef->GetName();
ppropDef->Release();
pprops->Release();
或者 (使用FdoPtr)
FdoPtr<FdoPropertyDefinitionCollectionpprops = pclassDef-GetProperties();
FdoPtr<FdoPropertyDefinitionppropDef = pprops-GetItem(0);
psz = propDef->GetName();
或者(还是使用FdoPtr)
psz = FdoPtr <FdoPropertyDefinition(FdoPtr <FdoPropertyDefinitionCollection>
(pclassDef->GetProperties())-GetItem(0))->GetName();