文章目录
Kernel SDK Developer’s Guide
Basic Operations-Work with Smart Pointers
Functionality of Smart Pointers
OdSmartPtr模板类和OdRxObjectPtr类提供了处理智能指针的公共功能。你可以以任何方式初始化它们:
MyObjPtr pSmart = OdRxObjectImpl<MyObj>::createObject();
OdRxObjectPtr pSmartRx = OdRxObjectImpl<MyObj>::createObject();
要获取智能指针指向的对象的方法或属性,请使用(- >)操作符,就像使用原始指针一样:
pSmart -> MyMethod();
pSmartRx -> MyProperty
;
要从智能指针获取原始指针,请使用get方法:
MyObj* pMy = pSmart.get();
OdRxObject* pObjRx = pSmartRx.get();
若要将智能指针设置为原始指针或另一个智能指针,请使用赋值运算符或构造函数。例如:
MyObjPtr pSmart1 = pMy;
MyObjPtr pSmart2 = pSmart;
MyObjPtr pSmart3(pMy, kOdRxObjAttach);
OdRxObjectPtr pSmartRx1 = pObjRx;
OdRxObjectPtr pSmartRx2 = pSmartRx;
OdRxObjectPtr pSmartRx3(pObjRx, kOdRxObjAttach);
如果智能指针存储空值,则赋值操作符将分配智能指针的地址并增加指定实例的引用计数器。如果智能指针已经存储了另一个实例的地址,则赋值操作符将减除其引用计数器,为智能指针分配指定实例的地址,并增加指定实例的引用计数器。当赋值运算符递减当前实例的引用计数器时,它将检查计数器是否为零,并在其引用计数器变为零时销毁实例。在使用构造函数时,可以传递kOdRxObjAttach选项,该选项禁止引用计数器的递增。
赋值运算符检查类类型。如果智能指针是类型化的,也就是说,它是由OdSmartPtr类创建的,并且您试图分配具有另一种类型的实例的地址,那么分配操作符将生成异常。如果智能指针是非类型化的,也就是说,它是由OdRxObjectPtr类创建的,则可以分配从OdRxObject类派生的任何对象的地址,并且不会生成异常。
要比较两个智能指针,可以使用比较操作符(==)和(!=)来检查智能指针是否存储相同的地址。例如:
OdRxObjectImpl<MyObj> my1;
OdRxObjectImpl<MyObj> my2;
MyObjPtr pSmart1 = &my1;
MyObjPtr pSmart2 = &my2;
MyObjPtr pSmart3 = &my1;
odPrintConsoleString(L"\\n(p1==p2)?%d", (pSmart1 == pSmart2)); // 0 (false)
odPrintConsoleString(L"\\n(p1==p3)?%d", (pSmart1 == pSmart3)); // 1 (true)
odPrintConsoleString(L"\\n(p2!=p3)?%d", (pSmart2 != pSmart3)); // 1 (true)
要验证智能指针是否为空,可以使用isNull()方法,该方法在智能指针为空时返回一个真值,或者在智能指针存储实例地址时返回一个假值。如果创建智能指针时没有初始化,则默认将其设置为NULL。例如:
OdRxObjectImpl<MyObj> my3;
MyObjPtr pSmart1 = &my3;
MyObjPtr pSmart2;
odPrintConsoleString(L"\\n(p1==Null)?%d", pSmart1.isNull()); // 0 (false)
odPrintConsoleString(L"\\n(p2==Null)?%d", pSmart2.isNull()); // 1 (true)
若要在不增加引用计数器的情况下分配实例的地址,请使用attach()方法。attach()方法为智能指针分配指定实例的地址,但它不增加指定实例的引用计数器。attach()方法需要该指针。例如:
OdRxObjectImpl<MyObj> my;
odPrintConsoleString(L"\\nRefs=%d", my.numRefs()); // 1
MyObjPtr pSmart; // = null
pSmart.attach(&my); // = my
odPrintConsoleString(L"\\nRefs=%d", my.numRefs()); // 1
如果智能指针已经存储了另一个实例的地址,则attach()方法将递减另一个实例的引用计数器,分配指定实例的地址,并且不增加指定实例的引用计数器。继续这个示例:
OdRxObjectImpl<MyObj> myX;
MyObjPtr pSmartX = &myX; // = myX
odPrintConsoleString(L"\\nRefs=%d", myX.numRefs()); // 2
pSmartX.attach(&my); // = my
odPrintConsoleString(L"\\nRefs=%d", myX.numRefs()); // 1
odPrintConsoleString(L"\\nRefs=%d", my.numRefs()); // 1
要在不减少引用计数器的情况下清除智能指针,请使用detach()方法。detach()方法返回当前实例的地址,为智能指针设置一个空值,并且不减量当前实例的引用计数器。可以使用返回的值作为分离实例的原始指针。继续示例:
MyObj* pObj;
pObj = pSmart.detach(); // pSmart = null // pObj = my
odPrintConsoleString(L"\\nRefs=%d", my.numRefs()); // 1
要清除智能指针,请使用release()方法。release()方法为智能指针设置一个空值,减少当前实例的引用计数器,并在引用计数器变为零时销毁实例。继续这个示例:
MyObjPtr pSmart1 = OdRxObjectImpl<MyObj>::createObject();
MyObj* pMy = pSmart1.get();
odPrintConsoleString(L"\\nRefs=%d", pMy->numRefs()); // 1
MyObjPtr pSmart2 = pSmart1;
odPrintConsoleString(L"\\nRefs=%d", pMy->numRefs()); // 2
pSmart1.release();
odPrintConsoleString(L"\\nRefs=%d", pMy->numRefs()); // 1
pSmart2.release(); // 0 - object is destroyed
OdRxObjectPtr类类似于OdSmartPtr类,但是它允许您使用从OdRxObject派生的任何类的智能指针进行操作。您不需要为它定义智能指针类型。OdRxObjectPtr类是一个非类型化的智能指针。attach()方法需要OdRxObject类型的原始指针。方法的作用是:返回OdRxObject类型的原始指针。例如:
OdRxObjectPtr pSmartRx0 = OdRxObjectImpl<MyObj>::createObject();
OdRxObject* pObjRx = pSmartRx0.get();
odPrintConsoleString(L"\\nRefs=%d", pObjRx->numRefs()); // 1
OdRxObjectPtr pSmartRx1 = pSmartRx0; // = pObjRx
OdRxObjectPtr pSmartRx2 = pSmartRx1; // = pObjRx
odPrintConsoleString(L"\\nRefs=%d", pObjRx->numRefs()); // 3
OdRxObjectPtr pSmartRx3; // = null
pSmartRx3.attach(pObjRx) // = pObjRx
odPrintConsoleString(L"\\nRefs=%d", pObjRx->numRefs()); // 3
OdRxObjectImpl<MyObj> my;
pSmartRx3.attach(&my) // = my
odPrintConsoleString(L"\\nRefs=%d", pObjRx->numRefs()); // 2
pSmartRx2.detach() // = null
pSmartRx3.detach() // = null
odPrintConsoleString(L"\\nRefs=%d", pObjRx->numRefs()); // 2
pSmartRx1.release(); // = null
odPrintConsoleString(L"\\nRefs=%d", pObjRx->numRefs()); // 1
pSmartRx0.release(); // 0 - object is destroyed
OdSmartPtr类或OdRxObjectPtr类的析构函数在删除智能指针之前调用release()方法。因此,当智能指针作用域结束时,声明为自动变量、静态变量、结构成员或函数参数的智能指针会自动减少其自身实例的引用计数器。
Example of Assigning Smart Pointers
这个示例演示了在引用计数器具有标准实现时,如何为智能指针使用赋值操作。该示例在以下实现中使用了控制台应用程序项目:
#include "conio.h"
#include "OdaCommon.h"
#include "OdToolKit.h"
#include "..\\..\\Kernel\\Extensions\\ExServices\\ExHostAppServices.h"
#include "..\\..\\Kernel\\Extensions\\ExServices\\ExSystemServices.h"
class MyApp : public ExSystemServices
{
protected:
ODRX_USING_HEAP_OPERATORS(ExSystemServices);
public:
MyApp() {};
};
int main()
{
OdStaticRxObject<MyApp> svcs;
odInitialize(&svcs);
odPrintConsoleString(L"\\nCreating the static instance");
TestStaticExchange();
odPrintConsoleString(L"\\nReturn from Test");
getch();
odPrintConsoleString(L"\\n\\n");
odPrintConsoleString(L"\\nCreating the dynamic instance");
TestDynamicExchange();
odPrintConsoleString(L"\\nReturn from Test");
getch();
odUninitialize();
return 0;
}
MyObj类的定义如下:
class MyObj : public OdRxObject
{
public:
MyObj();
~MyObj();
};
typedef OdSmartPtr<MyObj> MyObjPtr;
测试功能实现如下:
void TestStaticExchange()
{
OdRxObjectImpl<MyObj> my1;
OdRxObjectImpl<MyObj> my2;
getch();
SmartPointerExchangeTest(&my1, &my2);
odPrintConsoleString(L"\\nReturn\\n refCounter1: %d\\t refCounter2: %d", my1.numRefs(), my2.numRefs());
getch();
}
void TestDynamicExchange()
{
MyObjPtr pSmart1 = OdRxObjectImpl<MyObj>::createObject();
MyObjPtr pSmart2 = OdRxObjectImpl<MyObj>::createObject();
getch();
SmartPointerExchangeTest(pSmart1, pSmart2);
odPrintConsoleString(L"\\nReturn\\n refCounter1: %d\\t refCounter2: %d", pSmart1->numRefs(), pSmart2->numRefs());
getch();
}
SmartPointerExchageTest()函数演示了智能指针交换值时的引用计数,得到一个空值,并在函数中传递:
void SmartPointerExchangeTest(MyObjPtr pSmart1, MyObjPtr pSmart2)
{
odPrintConsoleString(L"\\n1.Call &->(pSmart1),&->(pSmart2)\\n refCounter1: %d\\t refCounter2: %d", pSmart1->numRefs(), pSmart2->numRefs());
getch();
MyObjPtr pSmart3 = pSmart1;
MyObjPtr pSmart4 = pSmart1;
odPrintConsoleString(L"\\n2.(pSmart1)->(pSmart3),(pSmart4)\\n refCounter1: %d\\t refCounter2: %d", pSmart1->numRefs(), pSmart2->numRefs());
getch();
MyObjPtr pSmart5 = pSmart2;
MyObjPtr pSmart6 = pSmart2;
odPrintConsoleString(L"\\n3.(pSmart2)->(pSmart5),(pSmart6)\\n refCounter1: %d\\t refCounter2: %d", pSmart1->numRefs(), pSmart2->numRefs());
getch();
pSmart5 = pSmart3;
odPrintConsoleString(L"\\n4.(pSmart3)->(pSmart5)\\n refCounter1: %d\\t refCounter2: %d", pSmart1->numRefs(), pSmart2->numRefs());
getch();
pSmart4 = pSmart6;
pSmart3 = pSmart6;
odPrintConsoleString(L"\\n5.(pSmart6)->(pSmart3),(pSmart4)\\n refCounter1: %d\\t refCounter2: %d", pSmart1->numRefs(), pSmart2->numRefs());
getch();
pSmart6 = pSmart5;
odPrintConsoleString(L"\\n6.(pSmart5)->(pSmart6)\\n refCounter1: %d\\t refCounter2: %d", pSmart1->numRefs(), pSmart2->numRefs());
getch();
pSmart3 = NULL;
pSmart5 = NULL;
odPrintConsoleString(L"\\n7.(pSmart3)=NULL,(pSmart5)=NULL\\n refCounter1: %d\\t refCounter2: %d", pSmart1->numRefs(), pSmart2->numRefs());
getch();
}
静态实例和动态实例的引用计数结果相同:
Object is created [counter: 1]
Object is created [counter: 1]
1.Call &->(pSmart1),&->(pSmart2)
refCounter1: 2 refCounter2: 2
2.(pSmart1)->(pSmart3),(pSmart4)
refCounter1: 4 refCounter2: 2
3.(pSmart2)->(pSmart5),(pSmart6)
refCounter1: 4 refCounter2: 4
4.(pSmart3)->(pSmart5)
refCounter1: 5 refCounter2: 3
5.(pSmart6)->(pSmart3),(pSmart4)
refCounter1: 3 refCounter2: 5
6.(pSmart5)->(pSmart6)
refCounter1: 4 refCounter2: 4
7.(pSmart3)=NULL,(pSmart5)=NULL
refCounter1: 3 refCounter2: 3
Return
refCounter1: 1 refCounter2: 1
Object is destroyed
Object is destroyed
Return from Test
当测试函数创建MyObj类的两个实例时,它们的引用计数器的值为1。测试函数时,通过两个实例的地址SmartPointerExchageTest()函数作为参数,它创建的第一个智能指针是指第一个实例和增量的引用计数器1 + 1 = 2,并创建第二个智能指针指的第二个实例,增加引用计数加1 1 + 1 = 2。当函数创建第三和第四个智能指针并将第一个智能指针的值赋给第一个实例时,它将第一个引用计数器增加2个2+2=4。类似地,当函数创建第五个和第六个智能指针并将第二个智能指针的值赋给第二个实例时,它将第二个引用计数器增加两个2+2=4。当函数将第三个智能指针的值赋给第五个智能指针时,它将第一个实例的引用计数器增加一个4+1=5,将第二个实例的引用计数器减少一个4 1=3。当第六智能指针的函数分配价值指的是第二个实例第三和第四智能指针指向第一个实例,它将第一个实例的引用计数器两5 2 = 3,第二个实例的引用计数器递增两个3 + 2 = 5。当第五智能指针的函数分配价值指的是第一个实例第六智能指针指的第二个实例,它第一个实例的引用计数器递增一个3 + 1 = 4,第二个实例的引用计数器的精神性5 1 = 4。当函数将NULL赋给引用第二个实例的第三个智能指针时,它将自己的引用计数器减1 4 1=3。类似地,当函数将NULL赋给第五个引用第一个实例的智能指针时,它将自己的引用计数器减1 4 1=3。当函数结束时,它会像自动对象一样销毁所有智能指针。销毁之前,智能指针的析构函数释放对指定对象的引用。第一个和第六个智能指针减少了第一个实例的引用计数器3 2=1。第二个和第四个智能指针减少第二个实例的引用计数器3 2=1。类似地,当TestStaticExchange()函数结束时,它会自动销毁所有静态实例。当TestDynamicExchange()函数结束时,它会销毁自己的智能指针,这些指针会递减引用计数器1 1=0。结果,引用计数器变为零,智能指针自动销毁动态实例。
Example of a Typified Smart Pointer
OdSmartPtr类是派生自OdRxObject的类的典型智能指针。您必须使用(typedef)语句为它定义一个新类型。例如,类定义:
class MyObj : public OdRxObject
{
public:
MyObj();
~MyObj();
};
typedef OdSmartPtr<MyObj> MyObjPtr;
测试功能实现如下:
void Test()
{
MyObjPtr pSmart0 = OdRxObjectImpl<MyObj>::createObject();
MyObjPtr* pObj = pSmart0.get();
odPrintConsoleString(L"\\nRefs=%d", pObj->numRefs()); // 1
MyObjPtr pSmart1 = pSmart0; // = pObj
MyObjPtr pSmart2 = pSmart1; // = pObj
odPrintConsoleString(L"\\nRefs=%d", pObj->numRefs()); // 3
MyObjPtr pSmart3; // = null
odPrintConsoleString(L"\\n(p1==Null)?%d", pSmart1.isNull()); // 0 (false)
odPrintConsoleString(L"\\n(p3==Null)?%d", pSmart3.isNull()); // 1 (true)
pSmart3.attach(pObj) // = pObj
odPrintConsoleString(L"\\nRefs=%d", pObj->numRefs()); // 3
OdRxObjectImpl<MyObj> my;
pSmart3.attach(&my) // = my
odPrintConsoleString(L"\\nRefs=%d", pObj->numRefs()); // 2
odPrintConsoleString(L"\\n(p1==p2)?%d", (pSmart1 == pSmart2)); // 1 (true)
odPrintConsoleString(L"\\n(p1==p3)?%d", (pSmart1 == pSmart3)); // 0 (false)
pSmart2.detach() // = null
pSmart3.detach() // = null
odPrintConsoleString(L"\\nRefs=%d", pObj->numRefs()); // 2
pSmart1.release(); // = null
odPrintConsoleString(L"\\nRefs=%d", pObj->numRefs()); // 1
pSmart0.release(); // 0 - object is destroyed
}
Example of a Non-Typified Smart Pointer
OdRxObjectPtr类是一个非类型化的智能指针,它可以处理从OdRxObject派生的任何类。您不需要为它定义一个新类型。例如,类定义:
class MyObj : public OdRxObject
{
public:
MyObj();
~MyObj();
};
测试功能实现如下:
void Test()
{
OdRxObjectPtr pSmartRx0 = OdRxObjectImpl<MyObj>::createObject();
OdRxObject* pObjRx = pSmartRx0.get();
odPrintConsoleString(L"\\nRefs=%d", pObjRx->numRefs()); // 1
OdRxObjectPtr pSmartRx1 = pSmartRx0; // = pObjRx
OdRxObjectPtr pSmartRx2 = pSmartRx1; // = pObjRx
odPrintConsoleString(L"\\nRefs=%d", pObjRx->numRefs()); // 3
OdRxObjectPtr pSmartRx3; // = null
odPrintConsoleString(L"\\n(Rx1==Null)?%d", pSmartRx1.isNull()); // 0 (false)
odPrintConsoleString(L"\\n(Rx3==Null)?%d", pSmartRx3.isNull()); // 1 (true)
pSmartRx3.attach(pObjRx) // = pObjRx
odPrintConsoleString(L"\\nRefs=%d", pObjRx->numRefs()); // 3
OdRxObjectImpl<MyObj> my;
pSmartRx3.attach(&my) // = my
odPrintConsoleString(L"\\nRefs=%d", pObjRx->numRefs()); // 2
odPrintConsoleString(L"\\n(Rx1==Rx2)?%d", (pSmartRx1 == pSmartRx2)); // 1 (true)
odPrintConsoleString(L"\\n(Rx1==Rx3)?%d", (pSmartRx1 == pSmartRx3)); // 0 (false)
pSmartRx2.detach() // = null
pSmartRx3.detach() // = null
odPrintConsoleString(L"\\nRefs=%d", pObjRx->numRefs()); // 2
pSmartRx1.release(); // = null
odPrintConsoleString(L"\\nRefs=%d", pObjRx->numRefs()); // 1
pSmartRx0.release(); // 0 - object is destroyed
}
暂无评论内容