JirR02 fec3fd845f Exercise 11 & Bonus 2
Added Exercise 11 & Bonus 2 to Repo
Added Signature to Exercise 10
2025-05-19 11:34:47 +02:00
..
2025-05-19 11:34:47 +02:00

Smart Pointers

Task

The objective of this problem is to implement a reference-count smart pointer, with functionality similar to that of a std::shared_ptr. Smart pointers implement the same functionality as regular pointers, but additionally they automatically take care of deallocating the object they point to when it is no longer needed. Reference-count smart pointers achieve this by allocating and maintaining a counter in memory together with the actual pointed-to object, which represents the number of smart pointers currently referencing the object. Any time a new smart pointer to an object is created or one is destroyed, this counter has to be incremented or decremented, respectively. When the last smart pointer to an object is destroyed, the counter will be decremented to

and the smart pointer will know that the object is no longer referenced; it can then deallocate the object.

The following example illustrates the process:

Smart a, b, c; 
a = Smart(new tracked()); 
// The smart pointer 'a' now points to the new
// tracked object with a reference count of 1.
c = Smart(new tracked()); 
// Another smart pointer 'c' now points to the
// second new tracked object with count 1.
b = a;                  
// 'a' and 'b' now both point to the first object,
// their shared counter is incremented to 2.
c = Smart();            
// A null smart pointer is assigned to 'c'; the
// smart pointer previously stored in 'c' is destroyed
// and its counter is decremented. Since the count
// is now zero, the second tracked object is deallocated.
return;
// At the end of the function, the smart 
// pointers 'a' and 'b' are both destroyed, their 
// counter is decremented twice, and the first 
// tracked object is deallocated.

Locations: The declarations of the smart pointer class (Smart) and member functions is provided in file smart.h. The implementation of member functions should be done in file smart.cpp. Smart pointers encapsulate pointers to objects of class tracked, which is declared in file smart.h.

Structure: In class Smart, member variable ptr represents the pointer (potentially shared by several object of class Smart) to the underlying pointed-to object. Member variable count represents the (shared) location containing the number of objects of class Smart currently holding the pointed-to object. Alternatively, both pointers may be nullptr, which corresponds to the notion of a null smart pointer. A null smart pointer does not manage any memory.

Objects pointed by smart pointers belong to class tracked, which is a linked list node where the next pointer is represented using a smart pointer. In particular, tests will use this structure to build linked lists with shared nodes, and check at the end that everything was correctly deallocated. To that end, every object of class tracked is tracked behind the scenes.

Steps:

  1. Implement the default constructor for class Smart. The default constructor should create a null smart pointer.
  2. Implement the constructor Smart(tracked* t). If t==nullptr, this should return a null smart pointer, otherwise, this should create a smart pointer to t with a reference count of \(1\). You may assume that t points to memory newly allocated by new that is not already being managed by another smart pointer.
  3. Implement the copy constructor Smart(const Smart& src) that returns a new smart pointer to the memory pointed to by src and increments the shared reference counter.
  4. Implement the destructor ~Smart(). For non-null pointers, it should decrement the reference counter and deallocate the pointed-to object if the resulting count is zero.
  5. Implement the assignment operator Smart& operator=(const Smart& src) that creates a copy of the provided smart pointer (incrementing its reference counter) and decrements the counter of the smart pointer of the left hand side of the assignment (and potentially deallocates the memory it points to).

Optional: Figure out the situations in which smart pointers are not suitable for memory management, in the sense that they may lead to memory leaks. You may look at the tests which leak memory for inspiration.

Note: In order to debug, you may execute code that you place in the function your_own_tests located in the smart.cpp file. The main function has a switch statement that chooses between a series of functions for different test scenarios. This switch defaults to your_own_tests. So if you enter -1 for test_id, your_own_tests will be executed.

Solutions

#include "smart.h"
#include "tracker.h"

Smart::Smart() {
  count = nullptr;
  ptr = nullptr;
}

Smart::Smart(tracked *t) /* TODO */ {
  if (t == nullptr) {
    count = nullptr;
    ptr = nullptr;
  } else {
    ptr = t;
    int *counter = new int;
    *counter = 1;
    count = counter;
  }
}

Smart::Smart(const Smart &src) /* TODO */ {
  count = src.count;
  ptr = src.ptr;
  if (count != nullptr)
    (*count)++;
}

Smart::~Smart() {
  if (count != nullptr) {
    (*count)--;
    if (*count == 0) {
      delete count;
      delete ptr;
      count = nullptr;
      ptr = nullptr;
    }
  }
}

Smart &Smart::operator=(const Smart &src) {
  if (src == *this)
    return *this;

  if (count != nullptr) {
    (*count)--;
    if (*count == 0) {
      delete count;
      delete ptr;
    }
  }

  count = src.count;
  ptr = src.ptr;

  if (count != nullptr)
    (*count)++;

  return *this;
}

tracked &Smart::operator*() { return *ptr; }

const tracked &Smart::operator*() const { return *ptr; }

tracked *Smart::operator->() { return ptr; }

const tracked *Smart::operator->() const { return ptr; }

bool Smart::operator==(const Smart &cmp) const { return (ptr == cmp.ptr); }

bool Smart::operator!=(const Smart &cmp) const { return !(*this == cmp); }

int Smart::get_count() const {
  if (this->count == nullptr)
    return 0;
  else
    return *(this->count);
}

void your_own_tests() {
  // EXTRA TESTS ?
}

// Answer to optional question
/*
FILL IN WITH YOUR ANSWER
*/

Made by JirR02 in Switzerland 🇨🇭