Middle+
How to write a smart pointer for one or multiple objects?
sobes.tech AI
Answer from AI
#include <atomic>
#include <utility>
// Simple smart pointer for a single object (similar to std::unique_ptr)
template <typename T>
class UniquePointer {
public:
// Constructor accepting a raw pointer
explicit UniquePointer(T* ptr = nullptr) : ptr_(ptr) {}
// Destructor
~UniquePointer() {
delete ptr_;
}
// Disable copying and assignment
UniquePointer(const UniquePointer&) = delete;
UniquePointer& operator=(const UniquePointer&) = delete;
// Allow moving
UniquePointer(UniquePointer&& other) noexcept : ptr_(other.ptr_) {
other.ptr_ = nullptr;
}
UniquePointer& operator=(UniquePointer&& other) noexcept {
if (this != &other) {
delete ptr_;
ptr_ = other.ptr_;
other.ptr_ = nullptr;
}
return *this;
}
// Access to the object
T* operator->() const { return ptr_; }
T& operator*() const { return *ptr_; }
// Get raw pointer
T* get() const { return ptr_; }
// Detach pointer
T* release() {
T* temp = ptr_;
ptr_ = nullptr;
return temp;
}
// Reset pointer
void reset(T* ptr = nullptr) {
if (ptr_ != ptr) {
delete ptr_;
ptr_ = ptr;
}
}
// Check for null
operator bool() const { return ptr_ != nullptr; }
private:
T* ptr_; // Raw pointer
};
// Simple smart pointer for one or multiple objects with reference counting (similar to std::shared_ptr)
template <typename T>
class SharedPointer {
private:
T* ptr_; // Raw pointer to object(s)
std::atomic<int>* ref_count_; // Pointer to reference count (atomic for thread safety)
public:
// Default constructor
SharedPointer() : ptr_(nullptr), ref_count_(nullptr) {}
// Constructor accepting a raw pointer
explicit SharedPointer(T* ptr) : ptr_(ptr), ref_count_(new std::atomic<int>(1)) {}
// Copy constructor
SharedPointer(const SharedPointer& other) : ptr_(other.ptr_), ref_count_(other.ref_count_) {
if (ref_count_) {
(*ref_count_)++; // Increment reference count
}
}
// Copy assignment operator
SharedPointer& operator=(const SharedPointer& other) {
if (this != &other) {
// Decrement current reference count
decrement_ref();
ptr_ = other.ptr_;
ref_count_ = other.ref_count_;
// Increment new reference count
if (ref_count_) {
(*ref_count_)++;
}
}
return *this;
}
// Move constructor
SharedPointer(SharedPointer&& other) noexcept : ptr_(other.ptr_), ref_count_(other.ref_count_) {
other.ptr_ = nullptr;
other.ref_count_ = nullptr;
}
// Move assignment operator
SharedPointer& operator=(SharedPointer&& other) noexcept {
if (this != &other) {
// Decrement current reference count
decrement_ref();
ptr_ = other.ptr_;
ref_count_ = other.ref_count_;
other.ptr_ = nullptr;
other.ref_count_ = nullptr;
}
return *this;
}
// Destructor
~SharedPointer() {
decrement_ref();
}
// Access to the object
T* operator->() const { return ptr_; }
T& operator*() const { return *ptr_; }
// Get raw pointer
T* get() const { return ptr_; }
// Get reference count
long use_count() const {
if (ref_count_) {
return ref_count_->load();
}
return 0;
}
// Check for null
operator bool() const { return ptr_ != nullptr; }
private:
// Helper to decrement reference count and delete if zero
void decrement_ref() {
if (ref_count_) {
if (--(*ref_count_) == 0) {
delete ptr_; // Delete object(s)
delete ref_count_; // Delete counter
ptr_ = nullptr;
ref_count_ = nullptr;
}
}
}
};
// Specialization for array (for SharedPointer)
template <typename T>
class SharedPointer<T[]> {
private:
T* ptr_; // Raw pointer to array
std::atomic<int>* ref_count_; // Pointer to reference count (atomic)
public:
// Constructor accepting raw pointer to array
explicit SharedPointer(T* ptr) : ptr_(ptr), ref_count_(new std::atomic<int>(1)) {}
// Copy constructor
SharedPointer(const SharedPointer& other) : ptr_(other.ptr_), ref_count_(other.ref_count_) {
if (ref_count_) {
(*ref_count_)++;
}
}
// Other constructors and operators similar to SharedPointer for single object,
// but destructor should use `delete[]`.
// Destructor for array
~SharedPointer() {
if (ref_count_) {
if (--(*ref_count_) == 0) {
delete[] ptr_; // Delete array
delete ref_count_;
ptr_ = nullptr;
ref_count_ = nullptr;
}
}
}
// Access array elements
T& operator[](size_t index) const { return ptr_[index]; }
// Get raw pointer
T* get() const { return ptr_; }
// Get reference count
long use_count() const {
if (ref_count_) {
return ref_count_->load();
}
return 0;
}
// Check for null
operator bool() const { return ptr_ != nullptr; }
};