template T my_max(const T& a, const T& b) { return (a > b) ? a : b; }
template <typename T>
class List_Node
{
public:
List_Node(const T& x) : data(x) { }
T data;
};
This lab is designed to give you some hands-on experience with simple Generic Programming using templates. This time, we will be implementing a Smart Pointer based on the STL.
There are several types of the Smart Pointers in the STL:
std::auto_ptr (has been removed in C++17)std::unique_ptrstd::shared_ptr std::weak_ptr std::unique_ptr.
Smart pointers are essentially raw pointers with extra features. One of the most notable features is automatic
memory management, which helps the user to avoid common dynamic memory issues such as dangling pointers and
memory leaks. With Smart Pointers, we no longer need to worry about managing our calls to new and
delete. Thus, using smart pointers are in a certain sense similar to the
garbage
collection functionality of Java.
Unique pointers (std::unique_ptr) are essentially pointers with one extra
assumption: there is only one pointer at a time pointing towards a particular object, hence "unique".
There are many cases where such an assumption would be useful. For example, suppose we have a raw pointer that is
the only reference towards a dynamically allocated object. If we reassign this pointer to somewhere else, we would
need to explicitly call delete on the original object to prevent memory leaks. This causes additionally trouble for
the programmer. However, if we replace the raw pointer with std::unique_ptr, the
original object will automatically be deleted during the assignment operation, as the object has lost its only
pointer reference. Thus, we do not have to explicitly call delete anymore.
There are also cases where it is desirable to have multiple pointers pointing towards the same object. In this case,
shared pointers (std::shared_ptr) should be used instead.
my_unique_ptr.h.
In this lab, we implement a minimal version of std::unique_ptr called
my_unique_ptr. We use templating so that
my_unique_ptr can store a raw pointer of any arbitrary type.
T has a single data member
T* p, the raw pointer held by the unique pointer. The object pointed by
p is referred as the object owned by the unique pointer.
p set to nullptr.
my_unique_ptr()
p should be set to nullptr.
my_unique_ptr(T* p)
p.
p.
p when this constructor is called.
my_unique_ptr(my_unique_ptr<T>& x)
x. If
x currently owns an object, the newly constructed unique pointer will take
over ownership of that object.
x is not empty, initialize the unique pointer such that it now points to
the object owned by x. Then, set x as empty.
~my_unique_ptr()
my_unique_ptr& operator=(my_unique_ptr<T>& x)
x, and set x as empty.
T& operator*() const
p).
mptr,
*mptr should be equivalent to *p.
T* operator->() const
p.
mptr,
mptr->foo() should be equivalent to
p->foo().
T* get_pointer() const
p.
bool is_empty()
T* release()
void reset()
void reset(T* p)
p.
void swap(my_unique_ptr<T>& x)
x.
x, and vice
versa.
Constructor Tests:
Default Constructor... true
Parameterized Constructor... true
Copy Constructor and Sharing... true
Operator=() Tests:
Copy Assignment Operator... true
Reset Tests:
reset()... true
reset(T* p)... true
Swap Test:
swap()... true
Release Tests:
release()... true
Dereference and Pointer-to-Member Operator Tests:
operator*()... true
operator->()... true
Destructor Tests:
sw_temp should invoke destructors from sw_temp0 to sw_temp9.
sw_temp0 is destroyed.
sw_temp1 is destroyed.
sw_temp2 is destroyed.
sw_temp3 is destroyed.
sw_temp4 is destroyed.
sw_temp5 is destroyed.
sw_temp6 is destroyed.
sw_temp7 is destroyed.
sw_temp8 is destroyed.
sw_temp9 is destroyed.
sw1 and sw2 should invoke their destructors only once when main() exits.
sw2 is destroyed.
sw1 is destroyed.
Deadline: 14 November 2021 Sunday 23:59 HKT.
You may earn 1% course grade for this lab via Automated Grading on the
ZINC Online Submission System.
Please compress and submit my_unique_ptr.h as lab7.zip to ZINC.