// When unique_ptr is not enought: std::shared_ptr and std::make_shared, // and std::weak_ptr // std::shared_ptr uses a reference counter: unlike unique_ptr, there // can be multiple shared_ptr's pointing to the same data. The data // is deallocated when the reference counter decreases to zero. Each // share increases the counter. This way of memory mangagement is quite // common and is found in Swift and other languages. But it's not // capable of completely freeing the programmer from worrying about memory: // cyclic pointers will never decrease the count, requiring the programmer // to identify some pointers as "weak" (std:weak_ptr). But this can be // tricky, and in the worst case requires the construction of spanning trees. #include #include #include // requires -std=c++20 using namespace std; void shared_demo() { shared_ptr sx = make_shared(1); auto sy = make_shared(10); cout << sx.use_count() << " : should be 1\n"; sy = sx; // shared pointers can be "copied" cout << sx.use_count() << " : should now be 2, the 1 is shared\n"; auto sz = move(sx); // as well as "moved": sx is no longer a owner cout << sz.use_count() << " : still 2: no new share created\n"; cout << sx.use_count() << " : should be 0, share got moved\n"; //cout << *sx < other; }; void share_and_leak() { auto a = make_shared(); auto b = make_shared(); a->other = b; // copy constructor applied, so another share is created.. b->other = a; } struct fixed_mutual_share { int A[10]; weak_ptr other; }; void no_more_leak() { auto a = make_shared(); auto b = make_shared(); a->other = b; b->other = a; // pointers are weak, does not increase ref. counter //a->other->A[0] = 10; // can't use weak_ptr to access data directly a->other.lock()->A[0] = 10; // temporary upgrade to shared_ptr } /* template requires default_initializable && destructible && movable struct Cons { T car{}; // {} default-initializes T shared_ptr> cdr{}; Cons(T item, shared_ptr> next) { car = move(item); cdr = move(next); }//constructor }; */ int main() { shared_demo(); //while (1) share_and_leak(); while (1) no_more_leak(); return 0; }