智能指针

在Gamebryo中通过使用智能指针实现引用计数的半自动化。这通过NiPointer来实现,这个模板类重载了操作符,使得它的实例表现出来像一个标准的指针。然而,
智能指针自动地增加和减少它指向对象的引用计数,从而应用程序不在直接调用NiRefOjbect的引用计数函数。例如在函数中如果声明一个局部智能指针变量并指向对象A,那么对象A的引用技术在赋值的时候将会增加1。当函数返回的时候,这个局部的智能指针被摧毁(超出了作用域),对象A 的引用计数将会减少1。
约定俗成,每个从NiRefObject派生的Gameroy类都有一个方便的智能指针声明,它表现在类型名称上加“Ptr”(NiNodePtr、NiTriShapePtr等)。

NiNodePtr spParent = <some node>;

NiNodePtr spChild = NiNew NiNode; 
//spChild points to new object. Reference count is 1.

spParent->AttachChild(spChild); 
//Reference count of object pointed to by spChild is now 2, since NiNode objects use smart pointers to refer their children.
 
spParent->DetachChild(spChild); 
//Reference count of object pointed to by spChild decreases  to 1.
 
spChild = 0; 
//Reference count of object decreases to 0. Object is deleted.
做为NiRefObject 派生类对象的应用程序指针在交叉调用会减少某个对象智能指针引用计数的时候,这个对象也应该是个智能指针。例如,如果你从父节点中detach一个NiAVObject子对象时,但不想对象在被父结点detach的时候删除,那么你的代码中指向子对象的指针也应当是个智能指针。
 
永远不要对智能指针作delete调用,这一点非常重要。这是标准堆上的指针对象和智能指针对象的唯一的行为区别。在智能指针对象上调用delete操作,
那么不论这个智能指针指向的指针对象的引用计数是多少,该对象都会被删除。如果想释放一个智能指针对指向对象的引用(在智能指针因超出作用域被摧毁之前),将智能指针赋值为0即可 这样确保对象引用计数减少到0的时候摧毁,类似的永远不要对一个NiRefObject对象指针作delete操作,这将也会永久摧毁这个对象。
 
正如在NiRefObject中讨论的那样,智能指针智能指向在堆上动态分配的对象。永远不要将智能指针指向一个在栈上的对象(局部变量)。永远不要将智能指针指向一个静态的对象。

为了区别指针和智能指针,Gamebryo对常规指针使用“pk”前缀,对智能指针使用“sp”前缀
 
如果一个函数使用智能指针作为参数,那么不要把一个没有被其他智能指针引用的对象常规指针作为参数传入到函数中。如果这样做,那么这个对象指针将会被摧毁掉。接下来是这个问题详细描述:
    1 常规指针pkObject指向一个动态分配的对象,其引用计数为0。
    2 传输pkObject到一个智能指针参数,编译器隐式调用智能指针的构造函数将pkObject转换到一个临时的智能指针,并将对象的引用计数增加到1。
    3 在函数调用的作用域,这个临时智能指针通过调用智能指针的拷贝构造函数复制到一个局部智能指针中,并将对象的引用计数增加到2。
    4 当函数调用返回的时候,局部智能指针被摧毁,并将对象的引用计数减少到1。
    5 在调用完成的时候,临时智能指针对象也被摧毁,并将对象的引用计数减少到0,这导致对象被释放掉。
当处理引用计数对象的时候智能指针不是必须的,智能指针是一种简易的工具。NiRefObject包含IncRefCount函数和DecRefCount,可以直接通过这些函数添加和释放引用。智能系统是这些调用的一个简单包装。应用程序可以混合使用智能指针和手工修改引用计数。
智能指针系统提供了两个宏,一个永远定义智能指针类型另一个用来智能指针类型转换。类型定义的宏是NiSmartPointer(classname)。例子如下
NiSmartPointer(NiNode)
类型转换宏是NiSmartPointerCast(classname, pkObject)。如下是典型的使用:
NiAVObjectPtr spChild = <some pointer known to be an NiNode>;
NiNodePtr spNode = NiSmartPointerCast(NiNode, spChild);
注意类型转换时操作是静态的不是动态的,所以我们应当在知道要转换的指针是正确的类型的时候使用NiSmartPointerCast。

你可能感兴趣的:(指针)