Last active
April 22, 2020 11:07
-
-
Save jakab922/e3b906e7438be7851109c08364696585 to your computer and use it in GitHub Desktop.
C++ smart pointer implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <bits/stdc++.h> | |
using namespace std; | |
template <typename T> | |
class my_shared_ptr { | |
T *data; | |
int *ref_count; | |
void _possibly_destroy() { | |
if (*ref_count == 0) { | |
delete data; | |
delete ref_count; | |
data = nullptr; | |
ref_count = nullptr; | |
} | |
} | |
public: | |
my_shared_ptr() : data{nullptr}, ref_count{nullptr} {} | |
my_shared_ptr(T *_data) : data{_data}, ref_count{new int{1}} {} | |
// copy constructor | |
my_shared_ptr(const my_shared_ptr<T> &other) { | |
data = other.data; | |
ref_count = other.ref_count; | |
(*ref_count)++; | |
} | |
// copy assignment operator | |
my_shared_ptr<T> &operator=(const my_shared_ptr<T> &other) { | |
if (other.data == data) return *this; | |
(*ref_count)--; | |
_possibly_destroy(); | |
data = other.data; | |
ref_count = other.ref_count; | |
(*ref_count)++; | |
return *this; | |
} | |
//move constructor | |
my_shared_ptr(my_shared_ptr<T> &&other) { | |
data = other.data; | |
ref_count = other.ref_count; | |
other.reset(); | |
} | |
// move assignment operator | |
my_shared_ptr<T> &operator=(my_shared_ptr<T> &&other) { | |
(*ref_count)--; | |
_possibly_destroy(); | |
data = other.data; | |
ref_count = other.ref_count; | |
other.reset(); | |
return *this; | |
} | |
~my_shared_ptr() { | |
if (ref_count == nullptr) return; // If it was resetted there isn't much to do here. | |
(*ref_count)--; | |
_possibly_destroy(); | |
} | |
size_t use_count() const { | |
return *ref_count; | |
} | |
T *get() { | |
return data; | |
} | |
void reset() { | |
data = nullptr; | |
ref_count = nullptr; | |
} | |
}; | |
int main() { | |
cout << "normal constructor" << endl; | |
my_shared_ptr<int> one{new int{1}}; // normal constructor | |
cout << "one.use_count(): " << one.use_count() << endl; // should be 1 | |
cout << endl | |
<< "copy constructor" << endl; | |
my_shared_ptr<int> other{one}; // copy constructor; | |
cout << "one.use_count(): " << one.use_count() << endl; // should be 2 | |
cout << "other.use_count(): " << other.use_count() << endl; // should also be 2 | |
assert(one.get() == other.get()); // They should point to the same object | |
cout << endl | |
<< "move constructor" << endl; | |
my_shared_ptr<int> third{my_shared_ptr<int>{new int{1}}}; // move constructor | |
cout << "third.use_count(): " << third.use_count() << endl; // should be 1 | |
assert(third.get() != nullptr); // Should point somewhere | |
cout << endl | |
<< "copy assignment" << endl; | |
other = third; // copy assignment operator | |
cout << "one.use_count(): " << one.use_count() << endl; // should be 1 | |
cout << "other.use_count(): " << other.use_count() << endl; // should be 2 | |
cout << "third.use_count(): " << third.use_count() << endl; // should be 2 | |
assert(other.get() == third.get() && one.get() != other.get()); | |
cout << endl | |
<< "move assignment first version" << endl; | |
one = my_shared_ptr<int>{new int{1}}; // Move assignment version 1 | |
cout << "one.use_count(): " << one.use_count() << endl; // should be 1 | |
cout << endl | |
<< "move assignment second version" << endl; | |
one = move(third); // Move assignment second case | |
cout << "one.use_count(): " << one.use_count() << endl; // Should be 2 | |
cout << "other.use_count(): " << other.use_count() << endl; // Should be 2 | |
assert(one.get() == other.get() && third.get() == nullptr); | |
my_shared_ptr<int> fourth; | |
assert(fourth.get() == nullptr); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment