-
Notifications
You must be signed in to change notification settings - Fork 198
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9560806
commit ba22906
Showing
4 changed files
with
147 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
BasedOnStyle: Google | ||
IndentWidth: 4 | ||
--- | ||
|
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
cmake_minimum_required(VERSION 3.16...3.23) | ||
|
||
project(UNIQUE_PTR_EXAMPLE) | ||
|
||
add_executable(main main.cpp) | ||
set_target_properties( | ||
main PROPERTIES | ||
CXX_STANDARD 20 | ||
CXX_EXTENSIONS OFF | ||
) |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
#include <iostream> | ||
#include <memory> | ||
#include <utility> | ||
#include <vector> | ||
|
||
template <class T> | ||
class unique_ptr { | ||
public: | ||
unique_ptr() noexcept : unique_ptr{nullptr} {} | ||
explicit unique_ptr(T *ptr) noexcept : m_ptr{ptr} {} | ||
|
||
unique_ptr(const unique_ptr &) = delete; | ||
unique_ptr &operator=(const unique_ptr &) = delete; | ||
|
||
unique_ptr(unique_ptr &&other) noexcept : m_ptr{other.release()} {} | ||
|
||
unique_ptr &operator=(unique_ptr &&other) noexcept { | ||
if (this != &other) { | ||
reset(other.release()); | ||
} | ||
return *this; | ||
} | ||
|
||
explicit operator bool() const noexcept { return static_cast<bool>(m_ptr); } | ||
|
||
T *get() const noexcept { return m_ptr; } | ||
T *operator->() const noexcept { return m_ptr; } | ||
T &operator*() const noexcept { return *m_ptr; } | ||
|
||
T *release() noexcept { return std::exchange(m_ptr, nullptr); } | ||
|
||
void reset(T *ptr = nullptr) noexcept { | ||
T *old = std::exchange(m_ptr, ptr); | ||
if (old) { | ||
delete old; | ||
} | ||
} | ||
|
||
~unique_ptr() noexcept { | ||
if (m_ptr) { | ||
delete m_ptr; | ||
} | ||
} | ||
|
||
private: | ||
T *m_ptr; | ||
}; | ||
|
||
template <class T, class... Args> | ||
unique_ptr<T> make_unique(Args &&...args) { | ||
return unique_ptr<T>(new T(std::forward<Args>(args)...)); | ||
} | ||
|
||
struct Widget { | ||
int val; | ||
|
||
explicit Widget(int val) : val{val} { | ||
std::cout << "ctor: " << val << '\n'; | ||
} | ||
|
||
virtual ~Widget() noexcept { std::cout << "dtor: " << val << '\n'; } | ||
}; | ||
|
||
void use_widget(const Widget *w) { | ||
std::cout << "yep, that's a widget: " << w->val << '\n'; | ||
} | ||
|
||
void use_widget(const Widget &w) { | ||
std::cout << "yep, that's a widget: " << w.val << '\n'; | ||
} | ||
|
||
void vector_raw_example() { | ||
std::vector<Widget *> widgets; | ||
const std::size_t count = 5; | ||
widgets.reserve(count); | ||
for (std::size_t i = 0; i < count; ++i) { | ||
widgets.push_back(new Widget(i)); | ||
} | ||
|
||
for (const auto &widget : widgets) { | ||
use_widget(widget); | ||
} | ||
|
||
delete widgets.back(); | ||
widgets.pop_back(); | ||
|
||
Widget *last = widgets.back(); | ||
widgets.pop_back(); | ||
|
||
std::cout << "last element was " << last->val << '\n'; | ||
|
||
delete last; | ||
|
||
for (std::size_t i = 0; i < widgets.size(); ++i) { | ||
delete widgets[i]; | ||
} | ||
} | ||
|
||
void vector_example() { | ||
std::vector<unique_ptr<Widget>> widgets; | ||
const std::size_t count = 5; | ||
widgets.reserve(count); | ||
for (std::size_t i = 0; i < count; ++i) { | ||
widgets.push_back(unique_ptr<Widget>(new Widget(i))); | ||
// widgets.push_back(make_unique<Widget>(i)); | ||
} | ||
|
||
for (const auto &widget : widgets) { | ||
use_widget(widget.get()); | ||
use_widget(*widget); | ||
} | ||
|
||
widgets.pop_back(); // automatically deleted | ||
|
||
unique_ptr<Widget> last = std::move(widgets.back()); | ||
widgets.pop_back(); | ||
|
||
std::cout << "last element was " << last->val << '\n'; | ||
} | ||
|
||
int main() { | ||
int *xp = new int(42); | ||
*xp = 0; | ||
delete xp; | ||
|
||
auto yp = std::make_unique<int>(42); | ||
*yp = 0; | ||
|
||
vector_example(); | ||
return 0; | ||
} |