Smart Pointers in C++

In this series of posts, Shreemoyee will dive into several recent additions to C++ which she has come to rely on in her work. The first installment will cover the latest in “smart pointers”

Introduction

Enter smart pointers:

A deep dive

class Entity {
private:
int entity_ = 0; // Default value initialized
public:
Entity() {
std::cout << "Constructing entity!"
<< std::endl;
}
Entity(const int& x) {
entity_ = x;
std::cout << "Constructing entity with an integer"
<< std::endl;
}
// Creating a copy constructor
Entity(const Entity& entity) {
entity_ = entity.entity_;
}
~Entity() {
std::cout << "Destructing entity!"
<< std::endl;
}
// Marked as const => can not assign data members here
void getEntity() const {
std::cout << "The entity is" << entity_
<< std::endl;
}
// const reference => no parameter modified here
void setEntity(const int& ent) {
entity_ = ent;
}
};

I. std::unique_ptr

#include <memory>
#include <Entity.h>
// Beginning of a scope
int main()
{
std::unique_ptr<Entity> e1 = std::make_unique<Entity>(6);
e1->getEntity(); // unique_ptr is smart, it does not
// need to be deleted -- it deallocates
// as it goes out of scope
// However, unique_ptr cannot be copied (it's copy
// constructor is deleted). So,
// std::unique_ptr<Entity> e2 = e1 does NOT work
std::unique_ptr<Entity> e2(std::move(e1)); // point to e1
// e1->getEntity() will fail because e1 has been freed
e2->getEntity();
} // End of main
Constructing entity with an integer!
The entity is 6
The entity is 6
Destructing entity!

II. std::shared_ptr

auto e1 = new Entity;
std::shared_ptr<Entity> shared_e1(e1);
std::shared_ptr<Entity> shared_e2(e1);
#include <memory>
#include <Entity.h>
// Outer scope
int main() {
std::shared_ptr<Entity> shared_e1 =
std::make_shared<Entity>(10);
// Let’s create an empty scope
{
// Shared pointer keeps track of reference counts
std::shared_ptr<Entity> e2 = shared_e1;
// This will alter shared_e1 as well, since
// both refer to the one address location of entity
e2->setEntity(2);
shared_e1->getEntity();
e2->getEntity();
}
// Destructor is called after this scope ends –
// only when BOTH go out of scope
std::cout << "Destructor NOT yet called"
<< std::endl;
} // End of main()
// Destructor is called here
Constructing entity with an integer!
The entity is 2
The entity is 2
Destructor NOT yet called
Destructing entity!

III. std::weak_ptr

#include <memory>
#include <Entity.h>
// Outer scope
int main()
{
std::shared_ptr<Entity> shared_e1
= std::make_shared<Entity>(14);
// Empty scope
{
std::weak_ptr<Entity> weak = shared_e1;
// Weak pointer does not increase the reference count
// We can NOT do weak->getEntity(); However:
// Use of lock()
std::shared_ptr<Entity> new_shared = weak.lock();
// Weak does NOT dangle yet
shared_e1 = nullptr;
// Weak now dangles and destructor is called
new_shared = nullptr;
if (weak.expired()) {
std::cout << "My weak pointer is dangling :("
<< std::endl;
}
// new_shared is now null; it is a
// bad practice, by the way
new_shared = weak.lock();
std::cout << new_shared << std::endl;
} // End of empty scope
} // End of main()
Constructing entity with an integer!
Destructing entity!
My weak pointer is dangling :(
0x0

The puzzles

Top 5 things to avoid

processEntity(std::shared_ptr<Entity>(new Entity), computePriority());
std::unique_ptr<Entity> e1  = std::make_unique<Entity>(6);
std::shared_ptr<Entity> shared_e3 = std::move(e1);

Epilogue

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
BlackRockEngineering

Official BlackRock Engineering Blog. From the designers & developers of industry-leading platform Aladdin®. Important disclosures: http://bit.ly/17XHCyc