-
Notifications
You must be signed in to change notification settings - Fork 0
om_unique_ptr
Taking the ownership of a dynamically allocated object, controlling its lifetime. The object is destructed if the pointer root itself is destructed.
Since there are various way to get memory from heap, om::unique_ptr allows to specify a custom destructor in the template. The library provides already three of them:
#include <omMemory.h>
struct Foo {
int food;
}
{ // starting some context
...
om::unique_ptr<Foo> var0 = new Foo; // uses om::_element_destructor by default
om::unique_ptr<Foo, om::_element_destructor> var1 = new Foo;
om::unique_ptr<Foo, om::_array_destructor> var2 = new Foo[5];
om::unique_ptr<Foo, om::_allocs_destructor> var3 = reinterpret_cast<Foo*>(malloc(sizeof(Foo)));
} // deletes all 4 objects using the correct destructors.
However, om::make_unique<T>(...)
is not yet implemented. Its exception safety is probably not of priority in Arduino environments.
-
om::_element_destructor
usesdelete
, -
om::_array_destructor
usesdelete[]
, -
om::_allocs_destructor
usesfree()
to clean up the heaps memory.
Some more examples:
struct Position {
int x, y, z;
};
om::unique_ptr<Position> p1 = new Position; // uses default om::_element_destructor
p1->x = 2018;
om::unique_ptr<float, om::_array_destructor> p2 = new float[20];
p2[3] = 3.14159;
p2[9] = p2[3] * 2.71;
om::unique_ptr<char, om::_allocs_destructor> name = reinterpret_cast<char*>(malloc(64));
memset(&(*name), 0, 64);
memset(name.get(), 0, 64); // same as above
-
unique_ptr();
Construct empty pointer. -
unique_ptr(T *ptr);
Constructs pointer and owns the object of type T. -
unique_ptr(unique_ptr &&other);
Constructs pointer and owns from RValue-pointer. See move(). -
unique_ptr& operator=(unique_ptr &&other);
Own object from RValue-pointer. Previously owned object instance is deleted. See move(). -
unique_ptr& operator=(T *ptr);
Own object of type T. Previously owned object instance is deleted. -
operator bool() const;
Check if pointer is not nullptr; -
T& operator* () const;
Return reference to owned object instance, example:(*p1).x
-
T* operator-> () const;
Return pointer to owned object instance, example:p1->x
-
T& operator[](uint32_t i) const;
Return reference to i-th element in array, example:p2[3]
-
unique_ptr move();
Returns new unique_ptr as RValue, (poor) replacement for missingstd::move()
. Grant ownership to RValue leaving a nullptr in this unique_ptr. -
T* release();
Releases ownership and returns pointer to object instance. -
void swap(unique_ptr &other);
Exchanges ownership between two unique_ptr. -
T* get() const;
Returns pointer, keep ownership. -
void reset(T* ptr = nullptr);
Drop ownership and free object instance. Take ownership of optionally provided new ptr. Operation is skipped, if ptr is already owned. -
~unique_ptr();
Destructor: Drop ownership and free object instance. (That's why we're here...!)
om::unique_ptr<char, om::_allocs_destructor> name = reinterpret_cast<char*>(malloc(64));
om::unique_ptr<char, om::_allocs_destructor> buffer;
// buffer = name;
// **** will fail during compile time, not allowed to duplicate ownership
buffer.swap(name); // ok, exchanges ownerships
// name = std::move(buffer);
// **** will fail during compile time, not available
name = buffer.move(); // implemented instead with costs of one additional copy ...
om::unique_ptr<char, om::_array_destructor> other = new char[100];
// other.swap(name);
// **** will fail during compile time, since destructors are not compatile!
// om::unique_ptr<char> test = "abcd";
// **** will fail during compile time, since compiler detects to delete a non-heap object!
If you would use a simple char*
as variable most of the cases above would pass through until your projects crashes during runtime.