I am writing my simple shared pointer. I am asking to review existing functions (understand that my implementations is not full, e.g now operator*)
Review please correctness
- Copy/move constructors and operator=
- Destructors
My code
template<typename T>
class my_shared_ptr {
public:
my_shared_ptr() {}
my_shared_ptr(T* ptr) {
ptr_ = ptr;
counter_ = new size_t(1);
}
my_shared_ptr(const my_shared_ptr& other) {
destroy_current();
ptr_ = other.ptr_;
counter_ = other.counter_;
if (other.ptr_ != nullptr) {
*counter_ += 1;
}
}
my_shared_ptr(my_shared_ptr&& other) {
ptr_ = other.ptr_;
counter_ = other.counter_;
other.ptr_ = nullptr;
other.counter_ = nullptr;
}
my_shared_ptr& operator=(const my_shared_ptr& other) {
destroy_current();
ptr_ = other.ptr_;
counter_ = other.counter_;
if (other.ptr_ != nullptr) {
*counter_ += 1;
}
}
my_shared_ptr&& operator=(my_shared_ptr&& other) {
ptr_ = other.ptr_;
counter_ = other.counter_;
other.ptr_ = nullptr;
other.counter_ = nullptr;
}
~my_shared_ptr() {
destroy_current();
}
private:
void destroy_current() {
if (counter_ and *counter_ > 1) {
*counter_ -= 1;
} else {
delete ptr_;
delete counter_;
}
}
private:
T* ptr_ = nullptr;
size_t* counter_ = nullptr;
};
template<typename T, typename... Args>
my_shared_ptr<T> make_my_shared(Args&&... args) {
auto ptr = new T(std::forward<Args>(args)...);
return my_shared_ptr<T>(ptr);
}
struct A {
int val_ = 0;
A(int val) : val_(val) { std::cout << "A(" << val_ << ")" << std::endl ; }
~A() { std::cout << "~A(" << val_ << ")" << std::endl ; }
};
int main() {
std::cout << "-----------\n";
{
my_shared_ptr<A> a1;
//my_shared_ptr<A> a2 = make_my_shared<A>(2);
my_shared_ptr<A> a2(new A(2));
{
my_shared_ptr<A> a3(new A(3));
std::cout << "log 1" << std::endl;
a1 = a3;
std::cout << "log 2" << std::endl;
a2 = a3;
std::cout << "log 3" << std::endl;
}
std::cout << "log 4" << std::endl;
}
std::cout << "Program finished!" << std::endl ;
}
std::shared_ptrhas some level of thread-safety. \$\endgroup\$single_thread_shared_ptrfor performance reasons, so ref counting can use cheap non-atomic operations, since ISO C++ doesn't have that; if you useshared_ptr, you get atomic RMW operations. So the problem here is the naming, not the lack of thread-safety. \$\endgroup\$