4.7 KiB
SmartPointer Documentation
uLib::SmartPointer<T> is a shared ownership smart pointer implementation designed for the uLib ecosystem. While it shares many similarities with std::shared_ptr, it includes specific features for legacy compatibility, local reference wrapping, and integrated Boost serialization.
Table of Contents
- Overview
- Key Differences from std::shared_ptr
- Common Usage
- Construction and Assignment
- Wrapping References
- Polymorphism and Casting
- Serialization
- Thread Safety
Overview
A SmartPointer manages the lifetime of an object through reference counting. When the last SmartPointer owning an object is destroyed or reset, the object is automatically deleted (unless a custom deleter is provided).
The implementation uses an internal ControlBlock to manage the reference count and an optional deleter function.
Key Differences from std::shared_ptr
| Feature | uLib::SmartPointer<T> |
std::shared_ptr<T> |
|---|---|---|
| Default Constructor | Initializes to nullptr. |
Initializes to nullptr. |
| Implicit Conversion | Implicitly converts from T* and to T*. |
Explicit construction from T*, no implicit conversion to T*. |
| Reference Wrapping | Direct support for wrapping T& with a no-op deleter. |
Requires explicit custom deleter [](T*){}. |
| Serialization | Built-in Boost.Serialization support. | Requires external serialization helpers. |
Note
The default constructor
SmartPointer<T>()now initializes tonullptr, matching standard C++ smart pointer behavior.
Common Usage
#include "Core/SmartPointer.h"
// 1. Allocation via default constructor (Allocates a new MyObject)
uLib::SmartPointer<MyObject> ptr;
// 2. Explicit null pointer
uLib::SmartPointer<MyObject> null_ptr(nullptr);
// 3. From raw pointer
uLib::SmartPointer<MyObject> manual_ptr(new MyObject(args));
// 4. Accessing members
ptr->DoSomething();
(*ptr).Value = 10;
// 5. Checking validity
if (ptr) {
// ...
}
Construction and Assignment
Allocation and Ownership
SmartPointer(): Initializes tonullptr(Standard behavior).SmartPointer(nullptr): Initializes to null.SmartPointer(T* ptr): Takes ownership of the raw pointer (implicit conversion allowed).SmartPointer(T& ref): Wraps an existing reference with a no-op deleter (implicit conversion allowed).SmartPointer(T* ptr, Deleter d): Takes ownership and uses a custom deleter.SmartPointer(const SmartPointer* other): Creates a copy from a pointer to anotherSmartPointer.
Move and Copy
- Supports standard copy and move semantics. Move operations transfer ownership without incrementing the reference count.
Pointer Access
get()/Get(): Returns the underlying raw pointer.operator T*(): Implicit conversion to raw pointer (legacy support).
Wrapping References
The SmartPointer can wrap an existing object (e.g., on the stack) without taking ownership:
MyObject stackObj;
uLib::SmartPointer<MyObject> spt(stackObj);
// spt will NOT delete stackObj when it goes out of scope.
Polymorphism and Casting
SmartPointer supports assignment between compatible types (base/derived). For explicit casting, use the following utilities:
uLib::static_pointer_cast<T>(ptr)uLib::dynamic_pointer_cast<T>(ptr)uLib::const_pointer_cast<T>(ptr)uLib::reinterpret_pointer_cast<T>(ptr)
Example:
uLib::SmartPointer<Derived> derived(new Derived());
uLib::SmartPointer<Base> base = derived; // Automatic upcast
auto derived2 = uLib::dynamic_pointer_cast<Derived>(base); // Downcast
Serialization
SmartPointer is fully integrated with boost::serialization. It tracks ControlBlock identity during serialization to ensure that multiple shared pointers to the same object are correctly reconstructed as a single shared instance.
#include <boost/archive/text_oarchive.hpp>
void save(const uLib::SmartPointer<MyObject>& ptr, std::ostream& os) {
boost::archive::text_oarchive oa(os);
oa << ptr;
}
Thread Safety
- The reference count is managed using
std::atomic<uint32_t>, making the increment/decrement operations thread-safe. - Note: While the reference counter itself is thread-safe, the object pointed to by the
SmartPointeris not automatically protected. Standard thread-safety rules for the underlying typeTapply. - Multiple threads can read the same
SmartPointerconcurrently. Concurrent modification (assignment/reset) of the sameSmartPointerinstance by different threads requires external synchronization.