Smart pointers (from <memory>, C++11) are RAII wrapper classes around a raw pointer — they call delete automatically in their destructor, making manual memory management largely unnecessary in modern C++.
#include <memory>
std::unique_ptr<int> uptr = std::make_unique<int>(42); // sole ownership
// no delete needed — freed automatically when uptr goes out of scope
std::shared_ptr<int> sptr1 = std::make_shared<int>(100); // shared ownership
std::shared_ptr<int> sptr2 = sptr1; // both now point to the same int
std::cout << sptr1.use_count() << "\n"; // 2 — reference count
std::weak_ptr<int> wptr = sptr1; // observes without affecting the count
std::unique_ptr<T> represents sole ownership — exactly one unique_ptr owns the object at a time. It can be moved (ownership transferred to another unique_ptr) but never copied, which the compiler enforces at compile time, making accidental double-ownership impossible. Use std::make_unique<T>(args...) to create one rather than unique_ptr<T>(new T(args...)) directly — it's safer with respect to exceptions during construction and is the recommended idiom.
std::shared_ptr<T> represents shared ownership via reference counting: each new shared_ptr copy increments an internal count, each destruction decrements it, and the underlying object is deleted only when the count reaches zero. This flexibility comes at a small performance cost (the reference count itself, and it must be updated atomically to be thread-safe) compared to unique_ptr, so unique_ptr should be the default choice, reaching for shared_ptr only when genuine shared ownership is required.
std::weak_ptr<T> holds a non-owning reference to an object managed by a shared_ptr, without affecting its reference count — its main purpose is breaking reference cycles (two shared_ptrs that indirectly point to each other, which would otherwise never reach a zero count and leak forever). As a rule, prefer smart pointers over raw new/delete in essentially all modern C++ code — raw pointers still have their place (observing an object you don't own, interfacing with C APIs), but owning memory is a job for a smart pointer.