commit 027b560053fa176bd58273caaef7412d0d876ef6 Author: karl Date: Thu Nov 28 11:42:21 2019 +0100 Basic UniquePtr functionality and tests diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..5f08175 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.15) +project(UniquePtr) + +set(CMAKE_CXX_STANDARD 17) + +add_executable(UniquePtr main.cpp) \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..8e95f1e --- /dev/null +++ b/main.cpp @@ -0,0 +1,117 @@ +#include + +class TestObject { +public: + TestObject() { + std::cout << "Constructor" << std::endl; + instanceCount += 1; + } + + TestObject(const TestObject &other) { + std::cout << "Copy constructor" << std::endl; + } + + ~TestObject() { + std::cout << "Destructor" << std::endl; + instanceCount -= 1; + } + + static void testPrint() { + std::cout << "testPrint" << std::endl; + } + + static int getInstanceCount() { + return instanceCount; + } + +private: + static int instanceCount; +}; + +int TestObject::instanceCount = 0; + +/// Holds unique ownership of a pointed to object and destroys it automatically +template +class UniquePtr { +public: + explicit UniquePtr(T *object) : object(object) {} + + /// Copy constructor + /// Shouldn't be used, since the pointer wouldn't be unique otherwise + UniquePtr(const UniquePtr &other) = delete; + + /// Move constructor + UniquePtr(UniquePtr &&other) : object(other.object) { + other.object = nullptr; + } + + /// Copy assignment operator + UniquePtr &operator=(const UniquePtr &) = delete; + + /// Move assignment operator + /// Shouldn't be used, since the pointer wouldn't be unique otherwise + UniquePtr &operator=(UniquePtr &&) = delete; + + /// Destructor + virtual ~UniquePtr() { + delete object; + } + + T operator*() const { + return *object; + } + + operator bool() const { + return object != nullptr; + } + + T *operator->() const { + return object; + } + + /// Release ownership of the owned object and return the pointer to it + T *Release() { + T *returnObject = object; + object = nullptr; + + return returnObject; + } + + /// Reset the internal pointer to null + void Reset() { + delete object; + + object = nullptr; + } + + /// Swaps the currently owned object with another + void Swap(T *other) { + delete object; + + object = other; + } + +private: + T *object; +}; + +int main() { + { + std::cout << "Constructing first pointer" << std::endl; + UniquePtr pointer = UniquePtr(new TestObject()); + + std::cout << "Calling test print via pointer" << std::endl; + pointer->testPrint(); + + std::cout << "Swapping for new object" << std::endl; + pointer.Swap(new TestObject()); + + std::cout << "Move constructing new pointer" << std::endl; + UniquePtr pointer2 = UniquePtr(std::move(pointer)); + } + + std::cout << std::endl << "All pointers should now be out of scope!" << std::endl; + std::cout << TestObject::getInstanceCount() << " instances left" << std::endl; + + return 0; +} \ No newline at end of file