Movatterモバイル変換


[0]ホーム

URL:


cppreference.com
Namespaces
Variants
    Actions

      std::shared_ptr

      From cppreference.com
      <cpp‎ |memory
       
       
      Memory management library
      (exposition only*)
      Allocators
      Uninitialized memory algorithms
      Constrained uninitialized memory algorithms
      Memory resources
      Uninitialized storage(until C++20)
      (until C++20*)
      (until C++20*)
      Garbage collector support(until C++23)
      (C++11)(until C++23)
      (C++11)(until C++23)
      (C++11)(until C++23)
      (C++11)(until C++23)
      (C++11)(until C++23)
      (C++11)(until C++23)
       
      std::shared_ptr
      Member functions
      Modifiers
      Observers
      (until C++20*)
      Non-member functions
      (until C++20)(until C++20)(until C++20)(until C++20)(until C++20)(C++20)
      functions(until C++26*)
      Helper classes
      Deduction guides(C++17)
       
      Defined in header<memory>
      template<class T>class shared_ptr;
      (since C++11)

      std::shared_ptr is a smart pointer that retains shared ownership of an object through a pointer. Severalshared_ptr objects may own the same object. The object is destroyed and its memory deallocated when either of the following happens:

      • the last remainingshared_ptr owning the object is destroyed;
      • the last remainingshared_ptr owning the object is assigned another pointer viaoperator= orreset().

      The object is destroyed usingdelete-expression or a custom deleter that is supplied toshared_ptr during construction.

      Ashared_ptr can share ownership of an object while storing a pointer to another object. This feature can be used to point to member objects while owning the object they belong to. The stored pointer is the one accessed byget(), the dereference and the comparison operators. The managed pointer is the one passed to the deleter when use count reaches zero.

      Ashared_ptr may also own no objects, in which case it is calledempty (an emptyshared_ptr may have a non-null stored pointer if the aliasing constructor was used to create it).

      All specializations ofshared_ptr meet the requirements ofCopyConstructible,CopyAssignable, andLessThanComparable and arecontextually convertible tobool.

      All member functions (including copy constructor and copy assignment) can be called by multiple threads on differentshared_ptr objects without additional synchronization even if these objects are copies and share ownership of the same object. If multiple threads of execution access the sameshared_ptr object without synchronization and any of those accesses uses a non-const member function ofshared_ptr then a data race will occur; thestd::atomic<shared_ptr> can be used to prevent the data race.

      Contents

      [edit]Member types

      Member type Definition
      element_type
      T(until C++17)
      std::remove_extent_t<T>(since C++17)
      weak_type(since C++17)std::weak_ptr<T>

      [edit]Member functions

      constructs newshared_ptr
      (public member function)[edit]
      destructs the owned object if no moreshared_ptrs link to it
      (public member function)[edit]
      assigns theshared_ptr
      (public member function)[edit]
      Modifiers
      replaces the managed object
      (public member function)[edit]
      swaps the managed objects
      (public member function)[edit]
      Observers
      returns the stored pointer
      (public member function)[edit]
      dereferences the stored pointer
      (public member function)[edit]
      (C++17)
      provides indexed access to the stored array
      (public member function)[edit]
      returns the number ofshared_ptr objects referring to the same managed object
      (public member function)[edit]
      (until C++20)
      checks whether the managed object is managed only by the currentshared_ptr object
      (public member function)[edit]
      checks if the stored pointer is not null
      (public member function)[edit]
      provides owner-based ordering of shared pointers
      (public member function)[edit]
      (C++26)
      provides owner-based hashing of shared pointers
      (public member function)[edit]
      provides owner-based equal comparison of shared pointers
      (public member function)[edit]

      [edit]Non-member functions

      creates a shared pointer that manages a new object
      (function template)[edit]
      creates a shared pointer that manages a new object allocated using an allocator
      (function template)[edit]
      appliesstatic_cast,dynamic_cast,const_cast, orreinterpret_cast to the stored pointer
      (function template)[edit]
      returns the deleter of specified type, if owned
      (function template)[edit]
      (removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20)
      compares with anothershared_ptr or withnullptr
      (function template)[edit]
      outputs the value of the stored pointer to an output stream
      (function template)[edit]
      specializes thestd::swap algorithm
      (function template)[edit]
      specializes atomic operations forstd::shared_ptr
      (function template)[edit]

      [edit]Helper classes

      atomic shared pointer
      (class template specialization)[edit]
      hash support forstd::shared_ptr
      (class template specialization)[edit]

      [edit]Deduction guides(since C++17)

      [edit]Notes

      Ownership of an object can only be shared through construction or assignment functions that receive anothershared_ptr object. If a newshared_ptr is constructed solely using the raw underlying pointer held by anothershared_ptr, this newshared_ptr will assume no othershared_ptr instances hold the object it possesses. This will result in (unless subsequent assignment occurs) the repeated application of the deleter to the same object during destruction.

      std::shared_ptr may be used with anincomplete typeT. However, the constructor from a raw pointer (template<class Y> shared_ptr(Y*)) and thetemplate<class Y>void reset(Y*) member function may only be called with a pointer to a complete type (note thatstd::unique_ptr may be constructed from a raw pointer to an incomplete type).

      TheT instd::shared_ptr<T> may be a function type: in this case it manages a pointer to function, rather than an object pointer. This is sometimes used to keep a dynamic library or a plugin loaded as long as any of its functions are referenced:

      void del(void(*)()){} void fun(){} int main(){    std::shared_ptr<void()> ee(fun, del);(*ee)();}

      [edit]Implementation notes

      In a typical implementation,shared_ptr holds only two pointers:

      • the stored pointer (one returned byget());
      • a pointer tocontrol block.

      The control block is a dynamically-allocated object that holds:

      • either a pointer to the managed object or the managed object itself;
      • the deleter (type-erased);
      • the allocator (type-erased);
      • the number ofshared_ptrs that own the managed object;
      • the number ofweak_ptrs that refer to the managed object.

      Whenshared_ptr is created by callingstd::make_shared orstd::allocate_shared, the memory for both the control block and the managed object is created with a single allocation. The managed object is constructed in-place in a data member of the control block. Whenshared_ptr is created via one of theshared_ptr constructors, the managed object and the control block must be allocated separately. In this case, the control block stores a pointer to the managed object.

      The pointer held by theshared_ptr directly is the one returned byget(), while the pointer/object held by the control block is the one that will be deleted when the number of shared owners reaches zero. These pointers are not necessarily equal.

      The destructor ofshared_ptr decrements the number of shared owners of the control block. If that counter reaches zero, the control block calls the destructor of the managed object. The control block does not deallocate itself until thestd::weak_ptr counter reaches zero as well.

      In existing implementations, the number of weak pointers is incremented ([1],[2]) if there is a shared pointer to the same control block.

      To satisfy thread safety requirements, the reference counters are typically incremented using an equivalent ofstd::atomic::fetch_add withstd::memory_order_relaxed (decrementing requires stronger ordering to safely destroy the control block).

      [edit]Example

      Run this code
      #include <chrono>#include <iostream>#include <memory>#include <mutex>#include <thread> usingnamespace std::chrono_literals; struct Base{    Base(){std::cout<<"Base::Base()\n";} // Note: non-virtual destructor is OK here    ~Base(){std::cout<<"Base::~Base()\n";}}; struct Derived:public Base{    Derived(){std::cout<<"Derived::Derived()\n";}     ~Derived(){std::cout<<"Derived::~Derived()\n";}}; void print(auto rem, std::shared_ptr<Base>const& sp){std::cout<< rem<<"\n\tget() = "<< sp.get()<<", use_count() = "<< sp.use_count()<<'\n';} void thr(std::shared_ptr<Base> p){std::this_thread::sleep_for(987ms);    std::shared_ptr<Base> lp= p;// thread-safe, even though the// shared use_count is incremented{staticstd::mutex io_mutex;std::lock_guard<std::mutex> lk(io_mutex);        print("Local pointer in a thread:", lp);}} int main(){    std::shared_ptr<Base> p=std::make_shared<Derived>();     print("Created a shared Derived (as a pointer to Base)", p); std::thread t1{thr, p}, t2{thr, p}, t3{thr, p};    p.reset();// release ownership from main     print("Shared ownership between 3 threads and released ownership from main:", p);     t1.join();    t2.join();    t3.join(); std::cout<<"All threads completed, the last one deleted Derived.\n";}

      Possible output:

      Base::Base()Derived::Derived()Created a shared Derived (as a pointer to Base)get() = 0x118ac30, use_count() = 1Shared ownership between 3 threads and released ownership from main:get() = 0, use_count() = 0Local pointer in a thread:get() = 0x118ac30, use_count() = 5Local pointer in a thread:get() = 0x118ac30, use_count() = 4Local pointer in a thread:get() = 0x118ac30, use_count() = 2Derived::~Derived()Base::~Base()All threads completed, the last one deleted Derived.

      [edit]Example

      Run this code
      #include <iostream>#include <memory> struct MyObj{    MyObj(){std::cout<<"MyObj constructed\n";}     ~MyObj(){std::cout<<"MyObj destructed\n";}}; struct Container:std::enable_shared_from_this<Container>// note: public inheritance{    std::shared_ptr<MyObj> memberObj; void CreateMember(){ memberObj=std::make_shared<MyObj>();}     std::shared_ptr<MyObj> GetAsMyObj(){// Use an alias shared ptr for memberreturn std::shared_ptr<MyObj>(shared_from_this(), memberObj.get());}}; #define COUT(str) std::cout << '\n' << str << '\n' #define DEMO(...) std::cout << #__VA_ARGS__ << " = " << __VA_ARGS__ << '\n' int main(){    COUT("Creating shared container");    std::shared_ptr<Container> cont=std::make_shared<Container>();    DEMO(cont.use_count());    DEMO(cont->memberObj.use_count());     COUT("Creating member");    cont->CreateMember();    DEMO(cont.use_count());    DEMO(cont->memberObj.use_count());     COUT("Creating another shared container");    std::shared_ptr<Container> cont2= cont;    DEMO(cont.use_count());    DEMO(cont->memberObj.use_count());    DEMO(cont2.use_count());    DEMO(cont2->memberObj.use_count());     COUT("GetAsMyObj");    std::shared_ptr<MyObj> myobj1= cont->GetAsMyObj();    DEMO(myobj1.use_count());    DEMO(cont.use_count());    DEMO(cont->memberObj.use_count());    DEMO(cont2.use_count());    DEMO(cont2->memberObj.use_count());     COUT("Copying alias obj");    std::shared_ptr<MyObj> myobj2= myobj1;    DEMO(myobj1.use_count());    DEMO(myobj2.use_count());    DEMO(cont.use_count());    DEMO(cont->memberObj.use_count());    DEMO(cont2.use_count());    DEMO(cont2->memberObj.use_count());     COUT("Resetting cont2");    cont2.reset();    DEMO(myobj1.use_count());    DEMO(myobj2.use_count());    DEMO(cont.use_count());    DEMO(cont->memberObj.use_count());     COUT("Resetting myobj2");    myobj2.reset();    DEMO(myobj1.use_count());    DEMO(cont.use_count());    DEMO(cont->memberObj.use_count());     COUT("Resetting cont");    cont.reset();    DEMO(myobj1.use_count());    DEMO(cont.use_count());}

      Output:

      Creating shared containercont.use_count() = 1cont->memberObj.use_count() = 0 Creating memberMyObj constructedcont.use_count() = 1cont->memberObj.use_count() = 1 Creating another shared containercont.use_count() = 2cont->memberObj.use_count() = 1cont2.use_count() = 2cont2->memberObj.use_count() = 1 GetAsMyObjmyobj1.use_count() = 3cont.use_count() = 3cont->memberObj.use_count() = 1cont2.use_count() = 3cont2->memberObj.use_count() = 1 Copying alias objmyobj1.use_count() = 4myobj2.use_count() = 4cont.use_count() = 4cont->memberObj.use_count() = 1cont2.use_count() = 4cont2->memberObj.use_count() = 1 Resetting cont2myobj1.use_count() = 3myobj2.use_count() = 3cont.use_count() = 3cont->memberObj.use_count() = 1 Resetting myobj2myobj1.use_count() = 2cont.use_count() = 2cont->memberObj.use_count() = 1 Resetting contmyobj1.use_count() = 1cont.use_count() = 0MyObj destructed

      [edit]See also

      (C++11)
      smart pointer with unique object ownership semantics
      (class template)[edit]
      (C++11)
      weak reference to an object managed bystd::shared_ptr
      (class template)[edit]
      Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/memory/shared_ptr&oldid=183067"

      [8]ページ先頭

      ©2009-2025 Movatter.jp