|
Pointer storage with deletion detection. More...
#include <weakPtr.h>
Inherits TfWeakPtrFacade< PtrTemplate, Type >.
Public Member Functions | |
TfWeakPtr (TfNullPtrType) | |
Construction, implicit conversion from TfNullPtr. | |
TfWeakPtr (std::nullptr_t) | |
Construction, implicit conversion from nullptr. | |
TfWeakPtr (TfWeakPtr const &p)=default | |
Copy construction. | |
TfWeakPtr (TfWeakPtr &&p) noexcept | |
Move construction. | |
template<class U > | |
TfWeakPtr (TfRefPtr< U > const &p, typename std::enable_if< std::is_convertible< U *, T * >::value >::type *dummy=0) | |
Conversion from RefPtr where U* is convertible to T* (this pointer type). | |
template<class U > | |
TfWeakPtr (U *p, typename std::enable_if< std::is_convertible< U *, T * >::value >::type *dummy=nullptr) | |
Explicitly construct from a raw pointer p. | |
template<class U > | |
TfWeakPtr (TfWeakPtr< U > const &p, typename std::enable_if< std::is_convertible< U *, T * >::value >::type *dummy=0) | |
TfWeakPtr & | operator= (TfWeakPtr const &p)=default |
Copy assignment. | |
TfWeakPtr & | operator= (TfWeakPtr &&p) noexcept |
Move assignment. | |
bool | IsExpired () const |
Friends | |
class | TfWeakPtrFacadeAccess |
Pointer storage with deletion detection.
Overview
A TfWeakPtr
is used to cache a pointer to an object; before retrieving/using this pointer, one queries the TfWeakPtr
object to verify that the objected pointed to has not been deleted in the interim.
In the code above, if PossiblyDeleteLemur()
deletes the object pointed to by lemur
, then the test if(lPtr)
returns false. Otherwise, it is safe to call a method on lPtr
.
To declare a TfWeakPtr<T>
, the type T
must publicly derive from TfWeakBase
.
Basic Use
A TfWeakPtr<T>
can access T's
public members by the ->
operator and can be dereferenced by the "\c *" operator.
A TfWeakPtr
converts to a true
bool value (for example, in an if
statement) only if the pointer points to an unexpired object. Otherwise, if the pointer was either initialized to NULL, or points to an expired object, the test returns false.
Occasionally, it is useful to distinguish between a TfWeakPtr
being explicitly initialized to NULL versus a TfWeakPtr
whose object has expired: the member function IsInvalid()
returns true
only if the pointer points to an expired object.
Opaqueness
See the parallel discussion about these concepts in the documentation for TfRefPtr
; the same concepts apply.
Comparisons, Const and Non-Const, Inheritance and Casting
See the parallel discussion about these concepts in the documentation for TfRefPtr
; the same concepts apply.
While it is possible to create TfWeakPtrs to const contents, we recommend against it. TfCreateNonConstWeakPtr will always create a non-const weak pointer even when passed a const argument (it casts away const).
The recommendation against use of weak pointers to const content is due to the fact that weak pointers cannot be implicitly cast for both inheritance (derived to base) and const-ness (non-const to const) at the same time. Because of this, using weak pointers to const content is most often much more trouble than the benefit it gives. Therefore our policy is to not use them.
Pointer Generality
While TfWeakPtr<TfWeakBase>
is specifically forbidden (you cannot construct this kind of object), you can assign any TfWeakPtr<T>
to a TfWeakPtr<void>
or TfWeakPtr<const void>. The only thing you can do with the latter is check to see if it points to an object that has expired. You cannot manipulate the object itself (i.e. access its member functions).
This is useful when you need to watch for object expiration without being bound by the type(s) of the objects you're watching. Similarly, you can create a TfWeakPtr<void> from a TfWeakBase
* using TfCreateWeakPtr()
.
Performance
Deriving from TfWeakBase
results in a single TfRefPtr
variable being added to a class, which is the size of a regular pointer. The cost of deleting an object derived from TfWeakBase
is an extra inline boolean comparison, and possible decrement of a reference count if the object's address was ever given out as a TfWeakPtr
.
The cost to create a TfWeakPtr
is as follows: initial creation of the pointer from a TfWeakBase
object dynamically creates an object called a remnant, whose size is that of two pointers. Subsequent transfers of the same object's address to another TfWeakPtr
merely bump a reference count to the remnant. When all TfWeakPtrs
to the object (and the object itself) are destroyed, the remnant is deleted. An object can have a remnant created and destroyed at most once, regardless of how many times its address is given out in the form of a TfWeakPtr
.
Summarizing, the cost of guarding an object is a small amount of extra space, and near-zero runtime cost if the guarding is never used. Even if the guarding is used, the overhead at deletion time is minimal.
The time to test if a TfWeakPtr
is NULL, or to call a member function through a TfWeakPtr
is small, involving only a single inline boolean comparison.
|
inline |
|
inline |
|
inlineexplicit |
|
friend |