memory.hpp
The memory.hpp header file is a fundamental component of the C++ Standard
Library Toolkit (CSLT), residing within the broader cslt namespace. This
file encapsulates a suite of smart pointer classes, including unique_ptr,
shared_ptr, and the forthcoming array_ptr. These classes are instrumental
in managing dynamically allocated memory in C++, offering automatic memory
management, resource control, and exception safety mechanisms.
Purpose
Memory management is a critical aspect of C++ programming. Manual memory management
using raw pointers is error-prone, leading to issues like memory leaks,
dangling pointers, and double frees. The memory.hpp file addresses these
challenges by providing robust abstractions that automate memory lifecycle management,
thus enhancing code safety, clarity, and reliability.
Classes
unique_ptr: Manages a dynamically allocated object, ensuring unique ownership semantics. It automates resource deallocation upon going out of scope, and it supports move semantics to transfer ownership.shared_ptr: Implements shared ownership over a dynamically allocated object. It uses reference counting to ensure that the object is deleted when the lastshared_ptrowning the resource is destroyed or reset.array_ptr(planned): Will provide specialized management for dynamic arrays, extending the smart pointer paradigm to collections of objects, ensuring safe allocation and deallocation through automatic memory management.
Importance in C++
The classes within memory.hpp reflect modern C++ practices, emphasizing safety,
efficiency, and expressiveness. They abstract away the complexities of manual
memory management, allowing developers to focus on application logic rather
than the intricacies of resource management. By leveraging these smart pointers,
programmers can write more robust and maintainable code, mitigate common memory
management errors, and utilize modern C++ features like move semantics and automatic
resource cleanup.
Note
The cslt namespace and its contents, including memory.hpp, are designed to complement the C++ Standard Library, offering an intuitive and cohesive toolkit for C++ developers.
By integrating these smart pointer classes into their projects, developers harness the power of automatic memory management, leading to cleaner, safer, and more efficient C++ codebases.
unique_ptr
The unique_ptr class is a part of the cslt namespace’s memory management
toolkit, encapsulated within the memory.hpp header file. It is designed to
manage the lifecycle of a dynamically allocated object, ensuring exclusive ownership
and automatic deletion when the unique_ptr goes out of scope or is otherwise
disposed of. This class is a cornerstone of resource management in modern C++,
eliminating the risks associated with raw pointer usage, such as memory leaks
and dangling pointers.
Purpose
unique_ptr offers a lightweight, efficient mechanism for managing dynamically
allocated memory. It provides strict ownership semantics, meaning that at any
given time, only one unique_ptr can own a particular resource. When the
owning unique_ptr is destroyed or assigned a new resource, it automatically
deletes the associated dynamically allocated object, ensuring proper resource cleanup.
Usage
To use unique_ptr, include the memory.hpp header and create an instance
of unique_ptr by passing a pointer to a dynamically allocated object.
unique_ptr takes full ownership of this object, managing its lifecycle automatically.
#include "memory.hpp"
cslt::unique_ptr<int> myPtr(new int(10));
Key Methods
- explicit unique_ptr(T* p)
Initializes a new
unique_ptrinstance, optionally taking a pointer to a dynamically allocated object.unique_ptrtakes full ownership of this object, managing its lifecycle automatically.- Parameters:
p (T*) – A pointer to a dynamically allocated object of type
T, ornullptrto indicate that theunique_ptrdoes not initially manage any object.
- unique_ptr(std::nullptr_t)
Initializes a new
unique_ptrinstance that does not manage any object initially.- Parameters:
std::nullptr_t – A
nullptrindicating that theunique_ptrdoes not manage any object.
- ~unique_ptr()
Automatically deletes the managed object when the
unique_ptrgoes out of scope, ensuring proper resource cleanup.
- T& operator*() const
Provides access to the underlying object.
- Returns:
A reference to the managed object of type
T.
- T* operator->() const
Provides access to the member functions of the managed object, behaving as if the
unique_ptrwas a pointer toT.- Returns:
A pointer to the managed object of type
T.
- const T* get() const
Returns a pointer to the managed object, or
nullptrif no object is being managed.- Returns:
A pointer to the managed object of type
T, ornullptrif no object is being managed.
- T* release()
Releases ownership of the managed object and returns a pointer to it. The
unique_ptrwill no longer manage the object and will not delete it when destroyed.- Returns:
A pointer to the previously managed object of type
T, ornullptrif there was no managed object.
- void reset(T* p = nullptr)
Deletes the currently managed object, if any, and takes ownership of a new object.
- Parameters:
p (T*) – A pointer to a new dynamically allocated object of type
T, ornullptrto make theunique_ptrnot manage any object.
- unique_ptr(unique_ptr&& move) noexcept
Move constructor that transfers ownership of the managed object from another
unique_ptr.- Parameters:
move (unique_ptr&&) – An rvalue reference to another
unique_ptrobject of the same type.
- unique_ptr& operator=(unique_ptr&& move) noexcept
Move assignment operator that transfers ownership of the managed object from another
unique_ptrand deletes the currently managed object, if any.- Parameters:
move (unique_ptr&&) – An rvalue reference to another
unique_ptrobject of the same type.- Returns:
A reference to *this
unique_ptrobject.
- explicit operator bool() const
Checks if the
unique_ptrcurrently manages an object.- Returns:
trueif theunique_ptrmanages an object, otherwisefalse.
Example
The following example demonstrates the basic usage of unique_ptr for
managing a dynamically allocated integer:
cslt::unique_ptr<int> ptr(new int(42));
std::cout << "Value: " << *ptr << std::endl; // Output: Value: 42
ptr.reset(new int(55));
std::cout << "New Value: " << *ptr << std::endl; // Output: New Value: 55
This example shows how to create a unique_ptr, access the managed object,
and replace it with a new dynamically allocated object using reset().
Note
unique_ptr is an essential tool for modern C++ developers, promoting safe and efficient memory management practices.
make_unique
The make_unique function is a utility within the cslt namespace, designed
to simplify the creation of unique_ptr instances. It encapsulates the pattern
of creating a dynamically allocated object and immediately transferring ownership
to a unique_ptr. This function is part of the memory.hpp header file and
serves as a safer, exception-friendly alternative to directly using new
with unique_ptr constructors.
Purpose
make_unique provides a convenient and safe way to create unique_ptr
instances without exposing raw pointers, thereby reducing the risk of memory
leaks and pointer-related errors. It also ensures that the object construction
is exception-safe by handling allocation and construction in a single step,
minimizing the chance of resource leaks in case of exceptions during object
construction.
Usage
To use make_unique, include the memory.hpp header file and call the
function with the desired object type and constructor arguments:
#include "memory.hpp"
auto myUniquePtr = cslt::make_unique<MyClass>(arg1, arg2, arg3);
make_unique automatically deduces the object type from the call and forwards
the provided arguments to the constructor of the specified type, returning a
unique_ptr that takes ownership of the newly created object.
Parameters
- template <typename T, typename... Args> unique_ptr<T> make_unique(Args&&... args)
Creates a dynamically allocated object of type
T, wrapping it in aunique_ptr. This function template simplifies the process of creating aunique_ptr, ensuring safe, exception-friendly allocation and initialization of resources.- Tparam T:
The type of the object to be created and managed by the returned
unique_ptr.- Tparam Args:
A variadic template parameter pack representing the types of arguments to be forwarded to the constructor of
T.- Parameters:
args (Args&&...) – The actual arguments to be forwarded to the constructor of
T, preserving their lvalue or rvalue nature through perfect forwarding.- Returns:
A
cslt::unique_ptr<T>managing the newly created object of typeT. Thisunique_ptrtakes ownership of the object, ensuring its proper deletion when theunique_ptrgoes out of scope or is otherwise disposed of.
Example
The make_unique function can be used to instantiate objects of any class that requires arguments for its constructor, automatically managing the object’s lifetime through a unique_ptr. Here is an example of its use:
struct Example {
Example(int x, const std::string& y) : num(x), str(y) {}
int num;
std::string str;
};
auto examplePtr = cslt::make_unique<Example>(42, "Hello World");
// examplePtr is a unique_ptr<Example> that owns an Example object initialized with 42 and "Hello World".
Note
The use of make_unique is highly recommended for safely creating dynamically allocated objects in modern C++. It encapsulates the best practices of resource management, combining safe allocation with automatic resource cleanup, thereby reducing the risk of memory leaks and pointer-related errors.
array_ptr
The array_ptr class within the cslt namespace provides a smart pointer
abstraction for managing dynamic arrays in C++. It encapsulates a pointer to a
dynamically allocated array of objects, ensuring automatic deallocation upon
destruction. This class is designed to facilitate memory management tasks,
offering mechanisms for array reallocation, and safe access patterns.
Purpose
Managing dynamic arrays in C++ requires careful handling of memory allocation and
deallocation to avoid memory leaks and undefined behavior. The array_ptr
class automates these tasks, providing a convenient and safer interface for working
with dynamically allocated arrays. It supports operations such as resizing the
array, releasing ownership of the array, and resetting the array with a new allocation.
Usage
To use array_ptr, include the header file where it is defined, and instantiate
an array_ptr object with the desired array size:
#include "memory.hpp" // Adjust the include path as necessary
cslt::array_ptr<int> myArray(10); // Creates an array_ptr managing an array of 10 integers
Key Features and Methods
- explicit array_ptr(std::size_t buff = 0)
Initializes a new
array_ptrinstance, optionally specifying the size of the array to allocate. This constructor allocates memory for an array of typeTwithbuffelements.- Parameters:
buff (std::size_t) – The size of the array to allocate. Defaults to 0, indicating no allocation.
- array_ptr(std::nullptr_t)
Initializes a new
array_ptrinstance that does not manage any array, effectively pointing tonullptr.- Parameters:
std::nullptr_t – A
nullptrindicating that thearray_ptrdoes not manage any array.
- ~array_ptr()
The destructor that automatically deallocates the managed array, ensuring proper resource cleanup.
- array_ptr(const array_ptr& other)
Copy constructor that creates a new
array_ptrinstance which makes a deep copy of the array managed byother, including allocating a new array and copying all elements.- Parameters:
other (const array_ptr&) – Another
array_ptrinstance to copy from.
- array_ptr& operator=(const array_ptr& other)
Copy assignment operator that assigns the current
array_ptrinstance to manage a deep copy of the array managed byother, including allocating a new array and copying all elements. Any previously managed array is properly deallocated.- Parameters:
other (const array_ptr&) – Another
array_ptrinstance to assign from.- Returns:
A reference to this
array_ptrinstance.
- array_ptr(array_ptr&& other) noexcept
Move constructor that transfers ownership of the managed array from
otherto this instance.otheris left in a valid but empty state.- Parameters:
other (array_ptr&&) – An rvalue reference to another
array_ptrinstance.
- array_ptr& operator=(array_ptr&& other) noexcept
Move assignment operator that transfers ownership of the managed array from
otherto this instance, properly deallocating any previously managed array.otheris left in a valid but empty state.- Parameters:
other (array_ptr&&) – An rvalue reference to another
array_ptrinstance.- Returns:
A reference to this
array_ptrinstance.
- void realloc(std::size_t buff, bool reduce_size = true)
Resizes the managed array to a new size, potentially allocating a new array and copying elements from the old array. Can optionally prevent reducing the array size based on the
reduce_sizeparameter.- Parameters:
buff (std::size_t) – The new size for the array.
reduce_size (bool) – Whether the function is allowed to reduce the array’s size (default is true).
- void reset(T* p = nullptr, std::size_t newLen = 0)
Replaces the managed array with a new array specified by
p, optionally of a different size specified bynewLen. The previously managed array is properly deallocated.- Parameters:
p (T*) – A pointer to a new array of type
T, ornullptr.newLen (std::size_t) – The size of the new array. Ignored if
pisnullptr.
- T* release()
Releases ownership of the managed array and returns a pointer to it. The
array_ptrinstance is reset to manage no array.- Returns:
A pointer to the previously managed array, or
nullptrif no array was managed.
- T& operator[](std::size_t index) const
Provides access to the element at the specified index in the managed array, with bounds checking.
- Parameters:
index (std::size_t) – The index of the element to access.
- Returns:
A reference to the element at the specified index.
- explicit operator bool() const
Checks if the
array_ptris currently managing an array.- Returns:
trueif thearray_ptrmanages an array, otherwisefalse.
Example
The following example demonstrates basic usage of array_ptr, including
instantiation, element access, and resizing:
cslt::array_ptr<int> arr(5); // Manages an array of 5 integers
for (std::size_t i = 0; i < arr.size(); ++i) {
arr[i] = static_cast<int>(i * 10); // Access and assign values to array elements
}
arr.realloc(10); // Resize the array to 10 elements
Note
The array_ptr class simplifies dynamic array management in C++, automating memory allocation and deallocation while providing safe access and modification mechanisms.
This documentation outlines the array_ptr class’s purpose, usage, key methods, and provides an example to help users understand how to utilize the class in their projects. Make sure to adjust paths and namespaces according to your project’s structure.