Unique Pointer Example

Here’s an example of using unique pointers. There are no memory leaks in this example.

Notice how using unique pointers can simplify memory management. When unique pointers are deleted, or their container is deleted, the memory they point to is automatically destroyed.

#include <stdio.h> #include <climits> #include <vector> #include <string> #include <string.h> #include <memory> // Forwarded from C++14 template<typename T, typename... Args> std::unique_ptr<T> make_unique(Args&&... args) { return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); } class Resource { public: Resource(int resources); std::unique_ptr<Resource> clone() const; int val; }; Resource::Resource(int resources) { val = resources; } std::unique_ptr<Resource> Resource::clone() const { return make_unique<Resource>(Resource(*this)); } class Job { public: Job(const char * name); //simple constructor Job(const Job &obj); //copy constructor ~Job(); //destructor void print(); int val; std::string s_name; char * c_name = nullptr; std::unique_ptr<Resource> resc = nullptr; }; Job::Job(const char * name) { val = 0; s_name = name; c_name = strdup(name); resc = make_unique<Resource>(1); } Job::Job(const Job &obj) { val = obj.val; s_name = obj.s_name; c_name = strdup(obj.c_name); // otherwise, when the original one is deleted, this would still point to freed memory resc = obj.resc->clone(); // this is necessary since unique_ptrs cannot be copied. We need to deep-copy the pointed-to object. // doing this in a "clone" method will allow us to use inheritance when we don't know the derived class } Job::~Job() { if (c_name) free(c_name); } void Job::print() { printf("%s has %d resources\n", s_name.c_str(), resc->val); } int main() { Job job1 = {"0.shecil"}; Job * job2 = new Job("1.shecil"); auto job3 = make_unique<Job>(Job("2.shecil")); std::vector<Job *> jobs1; jobs1.push_back(new Job("10.shecil")); jobs1.push_back(new Job("11.shecil")); jobs1.push_back(new Job("12.shecil")); std::vector<std::unique_ptr<Job>> jobs2; jobs2.push_back(make_unique<Job>(Job("22.shecil"))); jobs2.push_back(make_unique<Job>(Job("23.shecil"))); jobs2.push_back(make_unique<Job>(Job("24.shecil"))); // removing element from vectors delete jobs1.at(1); // delete the object jobs1.erase(jobs1.begin() + 1); // remove the raw pointer from the vector jobs2.erase(jobs2.begin() + 1); // remove the unique pointer from the vector, which will delete the object for (const auto &job : jobs1) { job->print(); } for (const auto &job : jobs2) { job->print(); } // deleting jobs // job1 does not need to be deleted, since when it leaves the scope, it will be deleted delete job2; // need to delete job2, since we allocated it with new // job3 does not need to be deleted, since when the unique_ptr leaves the scope, it will delete the pointed class // we need to delete the jobs in jobs1, since when the vector leaves scope, the raw pointers won't get freed for (const auto &job : jobs1) { delete job; } jobs1.clear(); // good manners to clear the array, otherwise the values are still pointers, but to bad memory // no need to delete the jobs in jobs2, as when the vector leaves the scope, it will be deleted, which will delete all the unique_ptrs return 0; }