Update: The code below has some obvious problems, and it is not allowed to revise code in the original question, so I have to post a new question, the revised code is here.
std::shared_ptr
has the potential problem that two pointer point to the same object but to different control blocks. And its atomic operation is pure overhead in a single threaded environment. So I wrote the following version to avoid these problems. This implementation also has the advantage that an empty pointer is the same size as a void *
.
template <typename T>
struct ThreadUnsafeSharedPtr {
private:
struct Pair {
T data;
size_t cnt;
template <typename ... Args>
Pair(Args && ... args): data(std::forward<Args>(args)...), cnt(1) {}
};
Pair *ptr;
public:
template <typename ... Args>
static ThreadUnsafeSharedPtr make(Args && ... args) {
ThreadUnsafeSharedPtr p;
p.ptr = new Pair(std::forward<Args>(args)...);
return p;
}
ThreadUnsafeSharedPtr() : ptr(nullptr) {}
ThreadUnsafeSharedPtr(const ThreadUnsafeSharedPtr & other) : ptr(other.ptr) {
if (ptr && &other != this) {
++(ptr->cnt);
}
}
ThreadUnsafeSharedPtr & operator=(const ThreadUnsafeSharedPtr & other) {
ptr = other.ptr;
if (ptr && &other != this) {
++(ptr->cnt);
}
return *this;
}
ThreadUnsafeSharedPtr(ThreadUnsafeSharedPtr && other) : ptr(other.ptr) {
if (&other != this) {
other.ptr = nullptr;
}
}
ThreadUnsafeSharedPtr & operator=(ThreadUnsafeSharedPtr && other) {
if (&other != this) {
ptr = other.ptr;
other.ptr = nullptr;
}
return *this;
}
~ThreadUnsafeSharedPtr() {
if (ptr) {
if(--ptr->cnt == 0) {
delete ptr;
}
}
}
};