A smart pointer is an object that holds a pointer and uses RAII to delete it automatically. With smart pointers you almost never need to write delete again. They live in <memory>.
unique_ptr: one owner
A unique_ptr is the only owner of its object. When the unique_ptr goes away, the object is deleted:
#include <iostream>
#include <memory>
#include <string>
using namespace std;
class Robot {
string name;
public:
Robot(string n) : name(n) { cout << name << " switched on\n"; }
~Robot() { cout << name << " switched off\n"; }
void wave() const { cout << name << " waves\n"; }
};
int main() {
unique_ptr<Robot> r = make_unique<Robot>("R2");
r->wave();
cout << "End of main\n";
return 0;
} // r is destroyed here, and it deletes the RobotOutput
R2 switched on R2 waves End of main R2 switched off
A unique_ptr can't be copied (there can only be one owner), but ownership can be handed over with move:
#include <iostream>
#include <memory>
using namespace std;
int main() {
unique_ptr<int> a = make_unique<int>(42);
unique_ptr<int> b = move(a); // b owns it now, a is empty
cout << (a == nullptr ? "a is empty" : "a has a value") << "\n";
cout << "b holds " << *b << "\n";
return 0;
}Output
a is empty b holds 42
shared_ptr: many owners
A shared_ptr can be copied. All copies share the object, and it is deleted when the last one goes away. use_count() tells you how many owners there are:
#include <iostream>
#include <memory>
#include <string>
using namespace std;
struct Song {
string title;
Song(string t) : title(t) {}
~Song() { cout << "Deleting " << title << "\n"; }
};
int main() {
shared_ptr<Song> s1 = make_shared<Song>("Imagine");
cout << "Owners: " << s1.use_count() << "\n";
{
shared_ptr<Song> s2 = s1; // a second owner
cout << "Owners: " << s1.use_count() << "\n";
}
cout << "Owners: " << s1.use_count() << "\n";
cout << "Now playing " << s1->title << "\n";
return 0;
}Output
Owners: 1 Owners: 2 Owners: 1 Now playing Imagine Deleting Imagine
Polymorphism with smart pointers
A vector of unique_ptr to a base class is the modern way to keep different kinds of objects together:
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
struct Shape {
virtual double area() const = 0;
virtual ~Shape() {}
};
struct Square : Shape {
double s;
Square(double side) : s(side) {}
double area() const override { return s * s; }
};
struct Rect : Shape {
double w, h;
Rect(double width, double height) : w(width), h(height) {}
double area() const override { return w * h; }
};
int main() {
vector<unique_ptr<Shape>> shapes;
shapes.push_back(make_unique<Square>(3));
shapes.push_back(make_unique<Rect>(2, 5));
for (const auto& s : shapes) {
cout << s->area() << "\n";
}
return 0; // every shape is deleted automatically
}Output
9 10
Remember: Use
unique_ptrby default. Useshared_ptronly when several parts of the program really need to share ownership. Avoid rawnew/delete.