Minor improvements
This commit is contained in:
parent
5fbac41ab2
commit
676eec88cc
171
main.cpp
171
main.cpp
@ -1,5 +1,95 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
/// Holds unique ownership of a pointed to object and destroys it automatically
|
||||||
|
template<class T>
|
||||||
|
class UniquePtr {
|
||||||
|
public:
|
||||||
|
/// Constructor without deleter
|
||||||
|
explicit UniquePtr(T *object) : object(object), deleter([](T *object) -> void { delete object; }) {
|
||||||
|
assert(object != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructor with custom deleter
|
||||||
|
/// Note that the custom deleter may not get a valid object (it could be a nullptr due to resetting, moving, etc)
|
||||||
|
UniquePtr(T *object, void (*deleter)(T *)) : object(object), deleter(deleter) {
|
||||||
|
assert(object != nullptr);
|
||||||
|
assert(deleter != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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), deleter(other.deleter) {
|
||||||
|
other.object = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Copy assignment operator
|
||||||
|
/// Shouldn't be used, since the pointer wouldn't be unique otherwise
|
||||||
|
UniquePtr &operator=(const UniquePtr &) = delete;
|
||||||
|
|
||||||
|
/// Move assignment operator
|
||||||
|
UniquePtr &operator=(UniquePtr &&other) {
|
||||||
|
object = other.object;
|
||||||
|
deleter = other.deleter;
|
||||||
|
|
||||||
|
other.object = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Destructor
|
||||||
|
virtual ~UniquePtr() {
|
||||||
|
deleter(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator*() const {
|
||||||
|
assert(object != nullptr);
|
||||||
|
|
||||||
|
return *object;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator bool() const {
|
||||||
|
return object != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
T *operator->() const {
|
||||||
|
assert(object != nullptr);
|
||||||
|
|
||||||
|
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() {
|
||||||
|
deleter(object);
|
||||||
|
|
||||||
|
object = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Swaps the currently owned object with another
|
||||||
|
void Swap(T *other) {
|
||||||
|
// TODO: This isn't really a "swap" but more of a "replace" - a proper swap would be std::swap(object, other);
|
||||||
|
// Not sure which one should be implemented, since I find this version more practical...
|
||||||
|
deleter(object);
|
||||||
|
|
||||||
|
object = other;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
T *object;
|
||||||
|
|
||||||
|
void (*deleter)(T *);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Simple object for testing constructor, destructor calls and potential memory leaks
|
||||||
class TestObject {
|
class TestObject {
|
||||||
public:
|
public:
|
||||||
TestObject() {
|
TestObject() {
|
||||||
@ -30,86 +120,9 @@ private:
|
|||||||
|
|
||||||
int TestObject::instanceCount = 0;
|
int TestObject::instanceCount = 0;
|
||||||
|
|
||||||
/// Holds unique ownership of a pointed to object and destroys it automatically
|
|
||||||
template<class T>
|
|
||||||
class UniquePtr {
|
|
||||||
public:
|
|
||||||
/// Constructor without deleter
|
|
||||||
explicit UniquePtr(T *object) : object(object), deleter(nullptr) {}
|
|
||||||
|
|
||||||
/// Constructor with deleter
|
|
||||||
UniquePtr(T *object, void (*deleter)(T*)) : object(object), deleter(deleter) {}
|
|
||||||
|
|
||||||
/// 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), deleter(other.deleter) {
|
|
||||||
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() {
|
|
||||||
deleteObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
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() {
|
|
||||||
deleteObject();
|
|
||||||
|
|
||||||
object = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Swaps the currently owned object with another
|
|
||||||
void Swap(T *other) {
|
|
||||||
deleteObject();
|
|
||||||
|
|
||||||
object = other;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
T *object;
|
|
||||||
void (*deleter)(T*);
|
|
||||||
|
|
||||||
void deleteObject() {
|
|
||||||
if (deleter != nullptr && object != nullptr) {
|
|
||||||
deleter(object);
|
|
||||||
} else {
|
|
||||||
delete object;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void customTestObjectDeleter(TestObject *object) {
|
void customTestObjectDeleter(TestObject *object) {
|
||||||
std::cout << "Custom deleter" << std::endl;
|
std::cout << "Custom deleter" << std::endl;
|
||||||
|
|
||||||
delete object;
|
delete object;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +139,7 @@ int main() {
|
|||||||
std::cout << "Swapping for new object" << std::endl;
|
std::cout << "Swapping for new object" << std::endl;
|
||||||
pointer.Swap(new TestObject());
|
pointer.Swap(new TestObject());
|
||||||
|
|
||||||
std::cout << "Move constructing new pointer" << std::endl;
|
std::cout << "Move assigning new pointer" << std::endl;
|
||||||
UniquePtr pointer2 = UniquePtr<TestObject>(std::move(pointer));
|
UniquePtr pointer2 = UniquePtr<TestObject>(std::move(pointer));
|
||||||
|
|
||||||
std::cout << "Constructing pointer with custom deleter" << std::endl;
|
std::cout << "Constructing pointer with custom deleter" << std::endl;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user