I3ISU_Opgave10

=Exercise 1 - Ensureing garbage collection on dynamically allocated std::string=

In this exercise we create a smart string, that is dynamically allocated, and will be deleted after use.

SmartString.h code format="cpp"
 * 1) include

class SmartString { public: SmartString(std::string* str); ~SmartString; std::string* get; std::string* operator->; std::string& operator*;

private: SmartString(const SmartString& other); void operator=(const SmartString& other);

std::string* str_; };

code

SmartString.cpp code format="cpp"
 * 1) include "SmartString.h"

SmartString::SmartString(std::string* str): str_(str) { }

SmartString::~SmartString {   delete str_; }

std::string* SmartString::get {   return str_; }

std::string* SmartString::operator-> {   return str_; }

std::string& SmartString::operator* {   return *str_; } code For testing, we have been supplied with the following program: code format="cpp"
 * 1) include
 * 2) include "SmartString.h"

int main {   SmartString ss(new std::string("Hello world")); std::cout << "String length: " << ss->length << std::endl;

if(ss->find("world") != std::string::npos) std::cout << "The 'ss' string does contain 'world'" << std::endl; else std::cout << "The 'ss' string does not contain 'world'" << std::endl;

}

code Full source code can be seen here

When running we get the following output code stud@goldenimage:~/Dropbox/Linux/ISu/Exc10/Debug$ ./10_1 String length: 11 The 'ss' string does contain 'world' code

> In this version, there is no support for changing the intern data. By making the copy constructor and the assignment operator, private and without implementation, they will have no effect > In our case it returns the pointer, to our resource, and make it avalible for use, with the functions defined for the class or data type.
 * **Why must the copy constructor and assignment operator be private with no implementation?**
 * **What exactly does the operator-> do?**

=Exercise 2 - The counter Pointer=

We now make a few changes to our SmartString.hpp to accommodate the new needs. SmartString.hpp code format="cpp" //============================================================================ // Name       : SmartString.hpp // Author     : Morten Godrim Jensen // Version    : 1.0 // Description : The Counted Pointer //============================================================================


 * 1) include
 * 2) include 

class SmartString { public: SmartString(std::string* str_); ~SmartString; std::string* get; std::string* operator->; std::string& operator*; SmartString(const SmartString& other); SmartString& operator=(const SmartString& other);

private: std::string* str_; unsigned int* counter_;

} code

We expand with a counter, so we are able to delete it if nothing is pointing at the SmartString. SmartString.cpp code format="cpp" //============================================================================ // Name       : SmartString.cpp // Author     : Morten Godrim Jensen // Version    : 1.0 // Description : The Counted Pointer //============================================================================


 * 1) include "SmartString.hpp"

SmartString::SmartString(std::string* str_) : str_(str_) { (*counter_)++; }

SmartString::~SmartString { if(--(*counter_)== 0) {   delete str_; delete counter_; } }

std::string* SmartString::get { return str_; }

std::string* SmartString::operator-> { return str_; }

std::string& SmartString::operator* { return *str_; }

SmartString::SmartString(const SmartString& other) : str_(other.str_) {   (*counter_)++; }

SmartString& SmartString::operator=(const SmartString& other) { if(this != &other) {     if(counter_-- == 0) {   delete str_; delete counter_; }

str_ = other.str_; counter_ = other.counter_; (*counter_)++; } return *this; } code

Lastly we expand the test program to make sure that we are counting and are able to deconstruct when we have zero pointers

Main.cpp code format="cpp" //============================================================================ // Name       : Main.cpp // Author     : Morten Godrim Jensen // Version    : 1.0 // Description : Testprogram of The Counted Pointer //============================================================================


 * 1) include "SmartString.hpp"

int main {   std::cout << "Contructor test:" << std::endl << std::endl;

SmartString ss(new std::string("Hello world"));

SmartString ss2 = ss;

std::cout << "Copy constructor test" << std::endl;

SmartString ss3(ss);

std::cout << "Destructor call ss3 " << std::endl; ss3.~SmartString;

std::cout << "Destructor call ss2 " << std::endl; ss2.~SmartString;

std::cout << "Destructor test" << std::endl; std::cout << "str_ inden delete:" << std::endl;

std::cout << "Destructor calls ss and the destuctor should now delete counter_ and str_ " << std::endl; ss.~SmartString; } code

 Why must the counter be dynamically allocated? Where should this happen? For at sikre at alle der referer til SmartString skal kunne tælle counteren op/ned. I Constructorens initialiseringsliste.

 How is the copy constructor be implemented? Den implementeres ved at ligge other.counter over i counter og tælle +1. Der oprettes en ny string str_ med adresse til other.string

 How is the assignment operator be implemented? Den tjekker om det der peges på skal nedlægges.

 What happens in the destructor and how should it be implemented? I destructoren tælles counteren -1 og hvis denne er 0. Slettes str_ og counter_. =Exercise 4 - Discarding our solution in favor of boost:shared_ptr<>= In this exercise we have to test the boost::shared_ptr<> from the boost library. We have in the following program tested with the use of a string. code format="cpp" using namespace std;
 * 1) include
 * 2) include
 * 3) include 

int main {   boost::shared_ptr ss1(new std::string("Hello World")); boost::shared_ptr ss2;

cout << "String 'ss1' contains: " << *ss1 << endl; cout << "String 'ss1' length: " << ss1->length << endl; cout << "Pointer is used " << ss1.use_count << " time" << endl;

ss2 = ss1;

cout << "Pointer is used " << ss1.use_count << " times" << endl;

{       boost::shared_ptr ss3; ss3 = ss2;

cout << "Pointer is used " << ss1.use_count << " times" << endl; cout << "String 'ss3' contains: " << *ss3 << endl; }

cout << "Pointer is used " << ss1.use_count << " times" << endl;

ss2.reset;

cout << "Pointer is used " << ss1.use_count << " time" << endl; ss1.reset; cout << "Pointer is used " << ss1.use_count << " time" << endl; return 0; }

code This program is testing assignment, function call on the target class and printing of the content. Then is the out of scope cleanup tested and the reset functions. When running the program we got the following result: code stud@goldenimage:~/$ ./main String 'ss1' contains: Hello World String 'ss1' length: 11 Pointer is used 1 time Pointer is used 2 times Pointer is used 3 times String 'ss3' contains: Hello World Pointer is used 2 times Pointer is used 1 time Pointer is used 0 time code By this we can conclude, that the boost::shared_ptr<> is working as intented.

=Exercise5 - Resource Handling= > Everything that is not directly a part of the program. It can be extern devices such as databases, it can be files or memory. > When you have pointers for resources, and pass them around between different functions and classes, you can loose track of how many is using the resource. When using smart pointers with the resources, we can eliminate this problem. > **Or when is it a must that somthing is allocated(on heap)?**You should only allocate on the heap, if you don't know the lifespan of the resource, or it can be changing size and shape during it's lifespan.
 * **What do you consider a resource?**
 * **In whichh situation do you foresee challenges with resources and how could they be handled?**
 * **In particular regarding memory, when would you be able to eliminate the need for allocations.**