From 1f3a5e9638751d29bd2336f95e94754660a936a8 Mon Sep 17 00:00:00 2001 From: XMuli Date: Sun, 18 Dec 2022 01:37:51 +0800 Subject: [PATCH] feat: C++ implementation of unique_ptr --- Studio/Studio/SharedPtr.h | 73 +++++++++++----- Studio/Studio/Studio.cpp | 13 +-- Studio/Studio/Studio.vcxproj | 2 + Studio/Studio/Studio.vcxproj.filters | 6 ++ Studio/Studio/UniquePtr.cpp | 1 + Studio/Studio/UniquePtr.h | 125 +++++++++++++++++++++++++++ 6 files changed, 186 insertions(+), 34 deletions(-) create mode 100644 Studio/Studio/UniquePtr.cpp create mode 100644 Studio/Studio/UniquePtr.h diff --git a/Studio/Studio/SharedPtr.h b/Studio/Studio/SharedPtr.h index 284a4b9..bed332f 100644 --- a/Studio/Studio/SharedPtr.h +++ b/Studio/Studio/SharedPtr.h @@ -92,26 +92,55 @@ private: // mutex* _pMutex; // 计数自增非原子操作,加锁解决多线程 }; -int main() -{ - SharedPtr sp1(new int(10)); - SharedPtr sp2(sp1); - *sp2 = 20; - //sp1 与 sp2 在管理这部分资源,引用计数为 2 - cout << sp1.useCount() << " *ptr:" << *sp1 << endl; //2 20 - cout << sp2.useCount() << " *ptr:" << *sp2 << endl; //2 20 - - SharedPtr sp3(new int(30)); - sp2 = sp3; //sp3 赋值给它,释放管理的旧资源,引用计数-1, - cout << sp1.useCount() << " *ptr:" << *sp1 << endl; //1 20 - cout << sp2.useCount() << " *ptr:" << *sp2 << endl; //2 30 - cout << sp3.useCount() << " *ptr:" << *sp3 << endl; //2 30 - - sp1 = sp3; - cout << sp1.useCount() << " *ptr:" << *sp1 << endl; //3 30 - cout << sp2.useCount() << " *ptr:" << *sp2 << endl; //3 30 - cout << sp3.useCount() << " *ptr:" << *sp3 << endl; //3 30 +//int main() +//{ +// SharedPtr sp1(new int(10)); +// SharedPtr sp2(sp1); +// *sp2 = 20; +// //sp1 与 sp2 在管理这部分资源,引用计数为 2 +// cout << sp1.useCount() << " *ptr:" << *sp1 << endl; //2 20 +// cout << sp2.useCount() << " *ptr:" << *sp2 << endl; //2 20 +// +// SharedPtr sp3(new int(30)); +// sp2 = sp3; //sp3 赋值给它,释放管理的旧资源,引用计数-1, +// cout << sp1.useCount() << " *ptr:" << *sp1 << endl; //1 20 +// cout << sp2.useCount() << " *ptr:" << *sp2 << endl; //2 30 +// cout << sp3.useCount() << " *ptr:" << *sp3 << endl; //2 30 +// +// sp1 = sp3; +// cout << sp1.useCount() << " *ptr:" << *sp1 << endl; //3 30 +// cout << sp2.useCount() << " *ptr:" << *sp2 << endl; //3 30 +// cout << sp3.useCount() << " *ptr:" << *sp3 << endl; //3 30 +// +// std::cout << "Hello World!\n"; +// return 0; +//} - std::cout << "Hello World!\n"; - return 0; -} \ No newline at end of file +/******************************************************************* + * 打印结果: + * no default constructor + * copy constructor + * addRefCount + * 2 *ptr:20 + * 2 *ptr:20 + * no default constructor + * copy assignment constructor + * release + * addRefCount + * 1 *ptr:20 + * 2 *ptr:30 + * 2 *ptr:30 + * copy assignment constructor + * release + * addRefCount + * 3 *ptr:30 + * 3 *ptr:30 + * 3 *ptr:30 + * Hello World! + * destructor + * release + * destructor + * release + * destructor + * release + ******************************************************************/ \ No newline at end of file diff --git a/Studio/Studio/Studio.cpp b/Studio/Studio/Studio.cpp index 3569b24..dd0513e 100644 --- a/Studio/Studio/Studio.cpp +++ b/Studio/Studio/Studio.cpp @@ -6,15 +6,4 @@ //int main() //{ // std::cout << "Hello World!\n"; -//} - -// Run program: Ctrl + F5 or Debug > Start Without Debugging menu -// Debug program: F5 or Debug > Start Debugging menu - -// Tips for Getting Started: -// 1. Use the Solution Explorer window to add/manage files -// 2. Use the Team Explorer window to connect to source control -// 3. Use the Output window to see build output and other messages -// 4. Use the Error List window to view errors -// 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project -// 6. In the future, to open this project again, go to File > Open > Project and select the .sln file +//} \ No newline at end of file diff --git a/Studio/Studio/Studio.vcxproj b/Studio/Studio/Studio.vcxproj index dad7e0f..cb3bc75 100644 --- a/Studio/Studio/Studio.vcxproj +++ b/Studio/Studio/Studio.vcxproj @@ -141,11 +141,13 @@ + + diff --git a/Studio/Studio/Studio.vcxproj.filters b/Studio/Studio/Studio.vcxproj.filters index 4a33b17..1cdf398 100644 --- a/Studio/Studio/Studio.vcxproj.filters +++ b/Studio/Studio/Studio.vcxproj.filters @@ -21,6 +21,9 @@ Source Files + + Source Files + @@ -32,5 +35,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/Studio/Studio/UniquePtr.cpp b/Studio/Studio/UniquePtr.cpp new file mode 100644 index 0000000..ee48038 --- /dev/null +++ b/Studio/Studio/UniquePtr.cpp @@ -0,0 +1 @@ +#include "UniquePtr.h" diff --git a/Studio/Studio/UniquePtr.h b/Studio/Studio/UniquePtr.h new file mode 100644 index 0000000..277bb0c --- /dev/null +++ b/Studio/Studio/UniquePtr.h @@ -0,0 +1,125 @@ +/******************************************************************* + * Copyright (c) 2022~2023 XMuli All rights reserved. + * GitHub: https://github.com/XMuli + * Description: C++ 实现一个核心的 unique_ptr 智能指针模板类; + * Ref: https://www.jianshu.com/p/77c2988be336 + * https://juejin.cn/post/7122641980315680782 + * https://juejin.cn/post/7099967913594978341 + ******************************************************************/ + +#pragma once +#include +using namespace std; + +template +class UniquePtr +{ +public: + constexpr UniquePtr() : _ptr(nullptr) { cout << "default constructor" << endl; }; + explicit UniquePtr(T* obj) : _ptr(obj) { cout << "no default constructor" << endl; }; + + UniquePtr(UniquePtr&& obj) noexcept + : _ptr(obj._ptr) + { + cout << "move constructor" << endl; + obj._ptr = nullptr; + } + UniquePtr& operator=(UniquePtr&& obj) noexcept + { + cout << "move assignment constructor" << endl; + if (&obj != this) { + if (obj._ptr) { + _ptr = obj._ptr; + obj._ptr = nullptr; + } + } + + return *this; + } + + UniquePtr(const UniquePtr& obj) = delete; // C++11 delete 禁止方式,C++98 用 private 来隐藏 + UniquePtr& operator=(const UniquePtr& obj) = delete; + + ~UniquePtr() + { + cout << "destructor" << endl; + if (_ptr) { + delete _ptr; + _ptr = nullptr; + } + } + + T& operator*() const { return *_ptr; } + T* operator->() const { return _ptr; } + T* get() const { return _ptr; } + + T* release() // return std::exchange(_ptr, nullptr); // C++14 + { + T* temp = _ptr; + _ptr = nullptr; + return temp; + } + + void reset(T* ptr) // std::exchange(_ptr, ptr); // C++14 + { + _ptr = ptr; + } + + void swap(UniquePtr& obj) + { + std::swap(_ptr, obj._ptr); + } + +private: + T* _ptr; +}; + +//int main() +//{ +// UniquePtr up1(new int(10)); +// cout << "up1:" << up1.get() << " *ptr:" << *up1 << endl; +// UniquePtr up2(std::move(up1)); // 控制权变更 +// cout << "up1:" << up1.get() << endl; // nullptr, 此时 up1 已无控制权 +// cout << "up2:" << up2.get() << " *ptr:" << *up2 << endl; +// +// UniquePtr up3(new int(30)); +// UniquePtr up4(new int(40)); +// cout << "up3:" << up3.get() << " *ptr:" << *up3 << endl; +// cout << "up4:" << up4.get() << " *ptr:" << *up4 << endl; +// up3 = std::move(up2); // 控制权变更 +// cout << "up3:" << up3.get() << " *ptr:" << *up3 << endl; +// cout << "up4:" << up4.get() << " *ptr:" << *up4 << endl; +// up3.swap(up4); +// cout << "up3:" << up3.get() << " *ptr:" << *up3 << endl; +// cout << "up4:" << up4.get() << " *ptr:" << *up4 << endl; +// +// up3.release(); +// cout << "up3:" << up3.get() << endl; +// +// std::cout << "Hello World!\n"; +// return 0; +//} + +/******************************************************************* + * 打印结果: + * no default constructor + * up1:01355E78 *ptr:10 + * move constructor + * up1:00000000 + * up2:01355E78 *ptr:10 + * no default constructor + * no default constructor + * up3:01355AF0 *ptr:30 + * up4:01355B20 *ptr:40 + * move assignment constructor + * up3:01355E78 *ptr:10 + * up4:01355B20 *ptr:40 + * up3:01355B20 *ptr:40 + * up4:01355E78 *ptr:10 + * up3:00000000 + * Hello World! + * destructor + * destructor + * destructor + * destructor + ******************************************************************/ \ No newline at end of file