feat: C++ implementation of unique_ptr

This commit is contained in:
XMuli 2022-12-18 01:37:51 +08:00
parent fa8e6f3c8b
commit 1f3a5e9638
No known key found for this signature in database
GPG Key ID: 9554B5DD5B8E986A
6 changed files with 186 additions and 34 deletions

View File

@ -92,26 +92,55 @@ private: //
mutex* _pMutex; // 计数自增非原子操作,加锁解决多线程 mutex* _pMutex; // 计数自增非原子操作,加锁解决多线程
}; };
int main() //int main()
{ //{
SharedPtr<int> sp1(new int(10)); // SharedPtr<int> sp1(new int(10));
SharedPtr<int> sp2(sp1); // SharedPtr<int> sp2(sp1);
*sp2 = 20; // *sp2 = 20;
//sp1 与 sp2 在管理这部分资源,引用计数为 2 // //sp1 与 sp2 在管理这部分资源,引用计数为 2
cout << sp1.useCount() << " *ptr:" << *sp1 << endl; //2 20 // cout << sp1.useCount() << " *ptr:" << *sp1 << endl; //2 20
cout << sp2.useCount() << " *ptr:" << *sp2 << endl; //2 20 // cout << sp2.useCount() << " *ptr:" << *sp2 << endl; //2 20
//
// SharedPtr<int> 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;
//}
SharedPtr<int> sp3(new int(30)); /*******************************************************************
sp2 = sp3; //sp3 赋值给它,释放管理的旧资源,引用计数-1 * :
cout << sp1.useCount() << " *ptr:" << *sp1 << endl; //1 20 * no default constructor
cout << sp2.useCount() << " *ptr:" << *sp2 << endl; //2 30 * copy constructor
cout << sp3.useCount() << " *ptr:" << *sp3 << endl; //2 30 * addRefCount
* 2 *ptr:20
sp1 = sp3; * 2 *ptr:20
cout << sp1.useCount() << " *ptr:" << *sp1 << endl; //3 30 * no default constructor
cout << sp2.useCount() << " *ptr:" << *sp2 << endl; //3 30 * copy assignment constructor
cout << sp3.useCount() << " *ptr:" << *sp3 << endl; //3 30 * release
* addRefCount
std::cout << "Hello World!\n"; * 1 *ptr:20
return 0; * 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
******************************************************************/

View File

@ -7,14 +7,3 @@
//{ //{
// std::cout << "Hello World!\n"; // 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

View File

@ -141,11 +141,13 @@
<ItemGroup> <ItemGroup>
<ClCompile Include="SharedPtr.cpp" /> <ClCompile Include="SharedPtr.cpp" />
<ClCompile Include="Studio.cpp" /> <ClCompile Include="Studio.cpp" />
<ClCompile Include="UniquePtr.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="MemoryAlignment.h" /> <ClInclude Include="MemoryAlignment.h" />
<ClInclude Include="SharedPtr.h" /> <ClInclude Include="SharedPtr.h" />
<ClInclude Include="SpecialMembers.h" /> <ClInclude Include="SpecialMembers.h" />
<ClInclude Include="UniquePtr.h" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">

View File

@ -21,6 +21,9 @@
<ClCompile Include="SharedPtr.cpp"> <ClCompile Include="SharedPtr.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="UniquePtr.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="MemoryAlignment.h"> <ClInclude Include="MemoryAlignment.h">
@ -32,5 +35,8 @@
<ClInclude Include="SharedPtr.h"> <ClInclude Include="SharedPtr.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="UniquePtr.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -0,0 +1 @@
#include "UniquePtr.h"

125
Studio/Studio/UniquePtr.h Normal file
View File

@ -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 <iostream>
using namespace std;
template <typename T>
class UniquePtr
{
public:
constexpr UniquePtr() : _ptr(nullptr) { cout << "default constructor" << endl; };
explicit UniquePtr(T* obj) : _ptr(obj) { cout << "no default constructor" << endl; };
UniquePtr(UniquePtr<T>&& obj) noexcept
: _ptr(obj._ptr)
{
cout << "move constructor" << endl;
obj._ptr = nullptr;
}
UniquePtr<T>& operator=(UniquePtr<T>&& obj) noexcept
{
cout << "move assignment constructor" << endl;
if (&obj != this) {
if (obj._ptr) {
_ptr = obj._ptr;
obj._ptr = nullptr;
}
}
return *this;
}
UniquePtr(const UniquePtr<T>& obj) = delete; // C++11 delete 禁止方式C++98 用 private 来隐藏
UniquePtr<T>& operator=(const UniquePtr<T>& 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<T>& obj)
{
std::swap(_ptr, obj._ptr);
}
private:
T* _ptr;
};
//int main()
//{
// UniquePtr<int> up1(new int(10));
// cout << "up1:" << up1.get() << " *ptr:" << *up1 << endl;
// UniquePtr<int> up2(std::move(up1)); // 控制权变更
// cout << "up1:" << up1.get() << endl; // nullptr, 此时 up1 已无控制权
// cout << "up2:" << up2.get() << " *ptr:" << *up2 << endl;
//
// UniquePtr<int> up3(new int(30));
// UniquePtr<int> 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
******************************************************************/