Ownership
Shared Ptr
std::shared_ptr allows several owners to share one object safely.
shared ownership
A `std::shared_ptr` keeps the object alive until the last shared owner is gone.
Shared Ptr
shared_ptr.cpp
Replay: real traced execution (multi-file project)
#include <iostream>
#include <memory>
class Counter {
private:
int value;
public:
Counter(int start) {
value = start;
}
void add(int amount) {
value += amount;
}
int current() {
return value;
}
};
int main() {
int start = 10;
int amount = 5;
std::shared_ptr<Counter> first = std::make_shared<Counter>(start);
{
std::shared_ptr<Counter> second = first;
second->add(amount);
std::cout << "insideOwners=" << first.use_count() << std::endl;
}
std::cout << "outsideOwners=" << first.use_count() << std::endl;
std::cout << "value=" << first->current() << std::endl;
return 0;
}
#include <iostream>
#include <memory>
class Counter {
private:
int value;
public:
Counter(int start) {
value = start;
}
void add(int amount) {
value += amount;
}
int current() {
return value;
}
};
int main() {
int start = 1;
int amount = 5;
std::shared_ptr<Counter> first = std::make_shared<Counter>(start);
{
std::shared_ptr<Counter> second = first;
second->add(amount);
std::cout << "insideOwners=" << first.use_count() << std::endl;
}
std::cout << "outsideOwners=" << first.use_count() << std::endl;
std::cout << "value=" << first->current() << std::endl;
return 0;
}
#include <iostream>
#include <memory>
class Counter {
private:
int value;
public:
Counter(int start) {
value = start;
}
void add(int amount) {
value += amount;
}
int current() {
return value;
}
};
int main() {
int start = 25;
int amount = 5;
std::shared_ptr<Counter> first = std::make_shared<Counter>(start);
{
std::shared_ptr<Counter> second = first;
second->add(amount);
std::cout << "insideOwners=" << first.use_count() << std::endl;
}
std::cout << "outsideOwners=" << first.use_count() << std::endl;
std::cout << "value=" << first->current() << std::endl;
return 0;
}
#include <iostream>
#include <memory>
class Counter {
private:
int value;
public:
Counter(int start) {
value = start;
}
void add(int amount) {
value += amount;
}
int current() {
return value;
}
};
int main() {
int start = 10;
int amount = 2;
std::shared_ptr<Counter> first = std::make_shared<Counter>(start);
{
std::shared_ptr<Counter> second = first;
second->add(amount);
std::cout << "insideOwners=" << first.use_count() << std::endl;
}
std::cout << "outsideOwners=" << first.use_count() << std::endl;
std::cout << "value=" << first->current() << std::endl;
return 0;
}
#include <iostream>
#include <memory>
class Counter {
private:
int value;
public:
Counter(int start) {
value = start;
}
void add(int amount) {
value += amount;
}
int current() {
return value;
}
};
int main() {
int start = 10;
int amount = 10;
std::shared_ptr<Counter> first = std::make_shared<Counter>(start);
{
std::shared_ptr<Counter> second = first;
second->add(amount);
std::cout << "insideOwners=" << first.use_count() << std::endl;
}
std::cout << "outsideOwners=" << first.use_count() << std::endl;
std::cout << "value=" << first->current() << std::endl;
return 0;
}
start ← 10, amount ← 5
22int main() {23 int start→ 10 = 10; //@start=1, 2524 int amount→ 5 = 5; //@amount=2, 102526 std::shared_ptr<Counter> first = std::make_shared<Counter>(start10);value ← 10
8public:9 Counter(int start10) {10 value→ 10 = start10;11 }first ← ⟨addr A⟩, second ← ⟨addr A⟩
26std::shared_ptr<Counter> first→ ⟨addr A⟩ = std::make_shared<Counter>(start10);2728{29 std::shared_ptr<Counter> second→ ⟨addr A⟩ = first⟨addr A⟩;30 second⟨addr A⟩->add(amount5);31 std::cout << "insideOwners=" << first.use_count() << std::endl;value ← 15
13void add(int amount5) {14 value→ 15 += amount5;15}second->add(amount);
29 std::shared_ptr<Counter> second = first;30 second⟨addr A⟩->add(amount5);31 std::cout << "insideOwners=" << first⟨addr A⟩.use_count() << std::endl;32}3334std::cout << "outsideOwners=" << first⟨addr A⟩.use_count() << std::endl;35std::cout << "value=" << first⟨addr A⟩->current() << std::endl;36return 0;outputinsideOwners=2 outsideOwners=1int current()
17int current() {18 return value15;19}std::cout << "value=" << first->current() << std::endl;
34 std::cout << "outsideOwners=" << first.use_count() << std::endl;35 std::cout << "value=" << first⟨addr A⟩->current() << std::endl;36 return 0;37}outputvalue=15
start ← 1, amount ← 5
22int main() {23 int start→ 1 = 1;24 int amount→ 5 = 5;2526 std::shared_ptr<Counter> first = std::make_shared<Counter>(start1);value ← 1
8public:9 Counter(int start1) {10 value→ 1 = start1;11 }first ← ⟨addr A⟩, second ← ⟨addr A⟩
26std::shared_ptr<Counter> first→ ⟨addr A⟩ = std::make_shared<Counter>(start1);2728{29 std::shared_ptr<Counter> second→ ⟨addr A⟩ = first⟨addr A⟩;30 second⟨addr A⟩->add(amount5);31 std::cout << "insideOwners=" << first.use_count() << std::endl;value ← 6
13void add(int amount5) {14 value→ 6 += amount5;15}second->add(amount);
29 std::shared_ptr<Counter> second = first;30 second⟨addr A⟩->add(amount5);31 std::cout << "insideOwners=" << first⟨addr A⟩.use_count() << std::endl;32}3334std::cout << "outsideOwners=" << first⟨addr A⟩.use_count() << std::endl;35std::cout << "value=" << first⟨addr A⟩->current() << std::endl;36return 0;outputinsideOwners=2 outsideOwners=1int current()
17int current() {18 return value6;19}std::cout << "value=" << first->current() << std::endl;
34 std::cout << "outsideOwners=" << first.use_count() << std::endl;35 std::cout << "value=" << first⟨addr A⟩->current() << std::endl;36 return 0;37}outputvalue=6
start ← 25, amount ← 5
22int main() {23 int start→ 25 = 25;24 int amount→ 5 = 5;2526 std::shared_ptr<Counter> first = std::make_shared<Counter>(start25);value ← 25
8public:9 Counter(int start25) {10 value→ 25 = start25;11 }first ← ⟨addr A⟩, second ← ⟨addr A⟩
26std::shared_ptr<Counter> first→ ⟨addr A⟩ = std::make_shared<Counter>(start25);2728{29 std::shared_ptr<Counter> second→ ⟨addr A⟩ = first⟨addr A⟩;30 second⟨addr A⟩->add(amount5);31 std::cout << "insideOwners=" << first.use_count() << std::endl;value ← 30
13void add(int amount5) {14 value→ 30 += amount5;15}second->add(amount);
29 std::shared_ptr<Counter> second = first;30 second⟨addr A⟩->add(amount5);31 std::cout << "insideOwners=" << first⟨addr A⟩.use_count() << std::endl;32}3334std::cout << "outsideOwners=" << first⟨addr A⟩.use_count() << std::endl;35std::cout << "value=" << first⟨addr A⟩->current() << std::endl;36return 0;outputinsideOwners=2 outsideOwners=1int current()
17int current() {18 return value30;19}std::cout << "value=" << first->current() << std::endl;
34 std::cout << "outsideOwners=" << first.use_count() << std::endl;35 std::cout << "value=" << first⟨addr A⟩->current() << std::endl;36 return 0;37}outputvalue=30
start ← 10, amount ← 2
22int main() {23 int start→ 10 = 10;24 int amount→ 2 = 2;2526 std::shared_ptr<Counter> first = std::make_shared<Counter>(start10);value ← 10
8public:9 Counter(int start10) {10 value→ 10 = start10;11 }first ← ⟨addr A⟩, second ← ⟨addr A⟩
26std::shared_ptr<Counter> first→ ⟨addr A⟩ = std::make_shared<Counter>(start10);2728{29 std::shared_ptr<Counter> second→ ⟨addr A⟩ = first⟨addr A⟩;30 second⟨addr A⟩->add(amount2);31 std::cout << "insideOwners=" << first.use_count() << std::endl;value ← 12
13void add(int amount2) {14 value→ 12 += amount2;15}second->add(amount);
29 std::shared_ptr<Counter> second = first;30 second⟨addr A⟩->add(amount2);31 std::cout << "insideOwners=" << first⟨addr A⟩.use_count() << std::endl;32}3334std::cout << "outsideOwners=" << first⟨addr A⟩.use_count() << std::endl;35std::cout << "value=" << first⟨addr A⟩->current() << std::endl;36return 0;outputinsideOwners=2 outsideOwners=1int current()
17int current() {18 return value12;19}std::cout << "value=" << first->current() << std::endl;
34 std::cout << "outsideOwners=" << first.use_count() << std::endl;35 std::cout << "value=" << first⟨addr A⟩->current() << std::endl;36 return 0;37}outputvalue=12
start ← 10, amount ← 10
22int main() {23 int start→ 10 = 10;24 int amount→ 10 = 10;2526 std::shared_ptr<Counter> first = std::make_shared<Counter>(start10);value ← 10
8public:9 Counter(int start10) {10 value→ 10 = start10;11 }first ← ⟨addr A⟩, second ← ⟨addr A⟩
26std::shared_ptr<Counter> first→ ⟨addr A⟩ = std::make_shared<Counter>(start10);2728{29 std::shared_ptr<Counter> second→ ⟨addr A⟩ = first⟨addr A⟩;30 second⟨addr A⟩->add(amount10);31 std::cout << "insideOwners=" << first.use_count() << std::endl;value ← 20
13void add(int amount10) {14 value→ 20 += amount10;15}second->add(amount);
29 std::shared_ptr<Counter> second = first;30 second⟨addr A⟩->add(amount10);31 std::cout << "insideOwners=" << first⟨addr A⟩.use_count() << std::endl;32}3334std::cout << "outsideOwners=" << first⟨addr A⟩.use_count() << std::endl;35std::cout << "value=" << first⟨addr A⟩->current() << std::endl;36return 0;outputinsideOwners=2 outsideOwners=1int current()
17int current() {18 return value20;19}std::cout << "value=" << first->current() << std::endl;
34 std::cout << "outsideOwners=" << first.use_count() << std::endl;35 std::cout << "value=" << first⟨addr A⟩->current() << std::endl;36 return 0;37}outputvalue=20
Count the Owners
firstowns theCounter.- Inside the block,
second = firstshares the same object. second->add(amount)changes the shared counter.- Leaving the block destroys
second. firstremains and still sees the updated value. | Moment | Owner count | Counter value | | --- | --- | --- | | inside block |2|15| | outside block |1|15|
Exercise: shared_ptr.cpp
Share one Counter inside a nested block, print owner counts, and keep the updated value afterward