Skip to content

Commit d2f9466

Browse files
committed
perf: improve AutoPtr
1 parent 4de4016 commit d2f9466

File tree

1 file changed

+115
-60
lines changed

1 file changed

+115
-60
lines changed

SmartPointers/AutoPtr.cpp

Lines changed: 115 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,152 @@
11
#include <iostream>
2+
#include <vector>
3+
#include <memory>
24

3-
template<typename Type>
4-
class AutoPtr
5+
template<typename T>
6+
struct auto_ptr_ref
57
{
8+
T* m_pointer;
9+
10+
auto_ptr_ref(T* pointer = nullptr) noexcept
11+
: m_pointer(pointer) {}
12+
};
13+
14+
template<typename T>
15+
class auto_ptr
16+
{
17+
using element_type = T;
618
public:
7-
explicit AutoPtr(Type* pointer) noexcept : mPointer(pointer) {}
8-
explicit AutoPtr(AutoPtr& another) noexcept;
9-
AutoPtr& operator = (AutoPtr& another) noexcept;
10-
Type operator * () const noexcept;
11-
Type* operator -> () const noexcept;
12-
operator bool() const noexcept;
13-
Type* get() const noexcept;
14-
Type* release() noexcept;
15-
void reset(Type* pointer = nullptr) noexcept;
16-
~AutoPtr();
19+
explicit auto_ptr(T* pointer = nullptr) noexcept
20+
: m_pointer(pointer) {}
21+
auto_ptr(auto_ptr& other) noexcept
22+
: m_pointer(other.release()) {}
23+
template<typename U>
24+
auto_ptr(auto_ptr<U>& other) noexcept
25+
: m_pointer(other.release()) {}
26+
auto_ptr(auto_ptr_ref<T> other) noexcept
27+
: m_pointer(other.m_pointer) {}
28+
T& operator=(auto_ptr& other) noexcept;
29+
template<typename U>
30+
T& operator=(auto_ptr<U>& other) noexcept;
31+
T& operator=(auto_ptr_ref<T> other) noexcept;
32+
~auto_ptr();
33+
T& operator*() const noexcept;
34+
T* operator->() const noexcept;
35+
T* get() const noexcept;
36+
T* release() noexcept;
37+
void reset(T* pointer = nullptr) noexcept;
38+
template<typename U>
39+
operator auto_ptr<U>() noexcept;
40+
template<typename U>
41+
operator auto_ptr_ref<U>() noexcept;
1742
private:
18-
Type* mPointer;
43+
T* m_pointer;
44+
};
45+
46+
template<>
47+
class auto_ptr<void>
48+
{
49+
public:
50+
using element_type = void;
1951
};
2052

21-
template<typename Type>
22-
AutoPtr<Type>::AutoPtr(AutoPtr& another) noexcept
53+
template<typename T>
54+
T& auto_ptr<T>::operator = (auto_ptr& other) noexcept
2355
{
24-
mPointer = another.mPointer;
25-
another.mPointer = nullptr;
56+
reset(other.release());
57+
return *this;
2658
}
2759

28-
template<typename Type>
29-
AutoPtr<Type>& AutoPtr<Type>::operator = (AutoPtr& another) noexcept
60+
template<typename T>
61+
template<typename U>
62+
T& auto_ptr<T>::operator = (auto_ptr<U>& other) noexcept
3063
{
31-
if (this != &another)
32-
{
33-
delete mPointer;
34-
mPointer = another.mPointer;
35-
another.mPointer = nullptr;
36-
}
37-
return *this;
64+
reset(other.release());
65+
return *this;
3866
}
3967

40-
template<typename Type>
41-
Type AutoPtr<Type>::operator * () const noexcept
68+
template<typename T>
69+
T& auto_ptr<T>::operator = (auto_ptr_ref<T> other) noexcept
4270
{
43-
return *mPointer;
71+
reset(other.m_pointer);
72+
return *this;
4473
}
4574

46-
template<typename Type>
47-
Type* AutoPtr<Type>::operator -> () const noexcept
75+
template<typename T>
76+
auto_ptr<T>::~auto_ptr()
4877
{
49-
return mPointer;
78+
delete m_pointer;
5079
}
5180

52-
template<typename Type>
53-
AutoPtr<Type>::operator bool() const noexcept
81+
template<typename T>
82+
T& auto_ptr<T>::operator * () const noexcept
5483
{
55-
return mPointer != nullptr;
84+
assert(m_pointer && "auto_ptr is not valid.");
85+
return *m_pointer;
5686
}
5787

58-
template<typename Type>
59-
Type* AutoPtr<Type>::get() const noexcept
88+
template<typename T>
89+
T* auto_ptr<T>::operator -> () const noexcept
6090
{
61-
return mPointer;
91+
assert(m_pointer && "auto_ptr is not valid.");
92+
return m_pointer;
6293
}
6394

64-
template<typename Type>
65-
Type* AutoPtr<Type>::release() noexcept
95+
template<typename T>
96+
T* auto_ptr<T>::get() const noexcept
6697
{
67-
Type* tmp = mPointer;
68-
mPointer = nullptr;
69-
return tmp;
98+
return m_pointer;
7099
}
71100

72-
template<typename Type>
73-
void AutoPtr<Type>::reset(Type* pointer) noexcept
101+
template<typename T>
102+
T* auto_ptr<T>::release() noexcept
74103
{
75-
delete mPointer;
76-
mPointer = pointer;
104+
T* temp_pointer = m_pointer;
105+
m_pointer = nullptr;
106+
return temp_pointer;
77107
}
78108

79-
template<typename Type>
80-
AutoPtr<Type>::~AutoPtr()
109+
template<typename T>
110+
void auto_ptr<T>::reset(T* pointer) noexcept
81111
{
82-
delete mPointer;
112+
if (m_pointer != pointer)
113+
{
114+
delete m_pointer;
115+
m_pointer = pointer;
116+
}
117+
}
118+
119+
template<typename T>
120+
template<typename U>
121+
auto_ptr<T>::operator auto_ptr<U>() noexcept
122+
{
123+
return auto_ptr<U>(release());
124+
}
125+
126+
template<typename T>
127+
template<typename U>
128+
auto_ptr<T>::operator auto_ptr_ref<U>() noexcept
129+
{
130+
return auto_ptr_ref<U>(release());
83131
}
84132

85133
int main()
86134
{
87-
// Test structure for testing
88-
struct Vector2d
89-
{
90-
double x, y;
91-
};
92-
93-
AutoPtr<Vector2d> ptr1(new Vector2d());
94-
AutoPtr<Vector2d> ptr2(ptr1);
95-
std::cout << "x: " << ptr2->x << " y: " << ptr2->y << std::endl;
96-
return EXIT_SUCCESS;
135+
auto_ptr<int> smart_ptr{ new int() };
136+
auto_ptr<int> another_smart_ptr{ smart_ptr };
137+
138+
auto_ptr_ref<int> smart_ptr_ref{ another_smart_ptr };
139+
140+
std::vector<auto_ptr_ref<int>> vector_smart_ptr_refs{ 5u };
141+
for (auto ref : vector_smart_ptr_refs)
142+
{
143+
ref = smart_ptr_ref;
144+
assert(ref.m_pointer);
145+
}
146+
147+
auto_ptr<int> result_smart_ptr{ smart_ptr_ref };
148+
assert(result_smart_ptr.get() && !smart_ptr.get() && !another_smart_ptr.get());
149+
150+
return EXIT_SUCCESS;
97151
}
152+

0 commit comments

Comments
 (0)