C++ weak_ptr creation performance

前端 未结 2 1008
醉话见心
醉话见心 2021-02-10 04:38

I\'ve read that creating or copying a std::shared_ptr involves some overhead (atomic increment of reference counter etc..).

But what about creating a std::weak_ptr from

2条回答
  •  北荒
    北荒 (楼主)
    2021-02-10 05:11

    In addition to Alec's very interesting description of the shared/weak_ptr system used in his previous projects, I wanted to give a little more detail on what is likely to be happening for a typical std::shared_ptr/weak_ptr implementation:

    // slow
    std::shared_ptr a(o);
    

    The main expense in the above construction is to allocate a block of memory to hold the two reference counts. No atomic operations need be done here (aside from what the implementation may or may not do under operator new).

    // slow
    std::shared_ptr b(a);
    

    The main expense in the copy construction is typically a single atomic increment.

    // slow ?
    std::weak_ptr c(b);
    

    The main expense in the this weak_ptr constructor is typically a single atomic increment. I would expect the performance of this constructor to be nearly identical to that of the shared_ptr copy constructor.

    Two other important constructors to be aware of are:

    std::shared_ptr d(std::move(a));  // shared_ptr(shared_ptr&&);
    std::weak_ptr e(std::move( c ));  // weak_ptr(weak_ptr&&);
    

    (And matching move assignment operators as well)

    The move constructors do not require any atomic operations at all. They just copy the reference count from the rhs to the lhs, and make the rhs == nullptr.

    The move assignment operators require an atomic decrement only if the lhs != nullptr prior to the assignment. The bulk of the time (e.g. within a vector>) the lhs == nullptr prior to a move assignment, and so there are no atomic operations at all.

    The latter (the weak_ptr move members) are not actually C++11, but are being handled by LWG 2315. However I would expect it to already be implemented by most implementations (I know it is already implemented in libc++).

    These move members will be used when scooting smart pointers around in containers, e.g. under vector>::insert/erase, and can have a measurable positive impact compared to the use of the smart pointer copy members.

    I point it out so that you will know that if you have the opportunity to move instead of copy a shared_ptr/weak_ptr, it is worth the trouble to type the few extra characters to do so.

提交回复
热议问题