share_ptr
#include <iostream>
#include <memory>
#include <thread>
#include <chrono>
#include <mutex>
struct Base {
Base() {
std::cout << "Base::Base()" << std::endl;
}
//note: non-virtual destruct is OK here
~Base() {
std::cout << "Base::~Base()\n";
}
};
struct Derive : public Base {
Derive() {
std::cout << "Derive::Derive()" << std::endl;
}
~Derive() {
std::cout << "Derive::~Derive()" << std::endl;
}
};
void thr(std::shared_ptr<Base> p) {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::shared_ptr<Base> lp = p; // thread-safe .
// even though the shared use_count is incremented
{
static std::mutex io_mutex;
std::lock_guard<std::mutex> lk(io_mutex);
std::cout << "local pointer in a thread: " << '\n' << " lp.get() "
<< lp.get() << " , lp.use_count() = " << lp.use_count() << '\n';
}
}
int main() {
std::shared_ptr<Base> p = std::make_shared<Derive>();
std::cout << "create a shared derive(as a pointer to base) \n" <<
"p.get() =" << p.get() << ", p.use_count() =" << p.use_count() << '\n';
std::thread t1(thr, p), t2(thr, p), t3(thr, p);
p.reset(); //release ownership from main
std::cout << "shared ownership between 3 threads and released\n"
<< "ownership from main:\n" << "p.get() =" << p.get() << ", p.use_count()="
<< p.use_count() << "\n";
t1.join();
t2.join();
t3.join();
}
unique_ptr
#include <iostream>
#include <memory>
#include <vector>
#include <cstdio>
#include <fstream>
#include <cassert>
#include <functional>
struct B {
virtual void bar() {
std::cout << "B::bar \n";
}
virtual ~B() = default;
};
struct D : public B {
D() {
std::cout << "D::D\n";
}
~D() {
std::cout << "D::~D\n";
}
void bar() override{
std::cout << "D::bar\n";
}
};
std::unique_ptr<D> pass_through(std::unique_ptr<D> p) {
p->bar();
return p;
}
void close_file(std::FILE *fp) {
std::fclose(fp);
}
int main() {
std::cout << "unique ownership semantics demo\n";
{
auto p = std::make_unique<D>(); //p is a unique_ptr that owns a D
auto q = pass_through(std::move(p));
assert(!p); // now p owns nothing and hold a null pointer
q->bar(); //q owns D object
} //~D called here
std::cout << "runtime polymorphism demo \n";
{
std::unique_ptr<B> p = std::make_unique<D>(); //p is a unique_ptr that owns D object as a pointer to the base
p->bar(); //virtual dispatch
std::vector<std::unique_ptr<B>> v;
v.push_back(std::make_unique<D>());
v.push_back(std::move(p));
v.emplace_back(new D);
for (auto& p : v) {
p->bar();
}
} //~D calls three times
std::cout << "custom deleter demo\n";
std::ofstream("demo.txt") << 'x'; //prepare
{
std::unique_ptr<std::FILE, decltype(&close_file)> fp(std::fopen("demo.txt", "r"), &close_file);
if (fp) //fopen could have failed; in which cause fp holds a null pointer
std::cout << (char)std::fgetc(fp.get()) << '\n';
} //fclose() called here, but only if FILE* is not a null pointer
std::cout << "Custom lambda-expression deleter demo\n";
{
std::unique_ptr<D, std::function<void(D*)>> p(new D, [](D* ptr) {
std::cout << "destorying from a custom deleter...\n";
delete ptr;
}); // p owns D
p->bar();
} // the lambda above is called and D is destoryed
std::cout << "Array form unique_ptr demo\n";
{
std::unique_ptr<D[]> p{ new D[3] };
} //calls ~D three times
}
weak_ptr
#include <iostream>
#include <memory>
std::weak_ptr<int> gw;
void observe() {
std::cout << "use_count == " << gw.use_count() << ": ";
if (auto spt = gw.lock()) { //has to be copied into a shared_ptr before usage
std::cout << *spt << "\n";
}
else {
std::cout << "gw is expired\n";
}
}
int main() {
{
auto sp = std::make_shared<int>(42);
gw = sp;
observe();
}
observe();
}