Understanding the aliasing shared_ptr constructor prototype

The prototype of the constructor construction aliasing shared_ptr g ++:

  template<typename _Yp>
    shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) noexcept
    : __shared_ptr<_Tp>(__r, __p) { }

The given example:

shared_ptr< pair<int,int> > pii(new pair<int,int>());
shared_ptr<int> pi(pii, &pii->first);

It works; always worked. But looking at the prototype, _Yp is the template parameter that we provide for instantiating the template, and therefore, the last line above seems like it should read:

shared_ptr<pair> pi(pii, &pii->first);

But definitely an example correct. So how do we explain this? I first looked at the prototype today, and I'm trying to figure out how to interpret it. Thanks for your comments / explanations.

+4
source share
2 answers

/ . _Yp , shared_ptr . shared_ptr GCC _Tp, _Yp. shared_ptr, _Tp element_type.

_Yp - , .

shared_ptr "" . _Tp _Yp - .

( ) _Yp. . _Tp, ,

shared_ptr<int> pi(pii, &pii->first);
           ^      ^
           |      |
           |      The `_Yp` parameter is kinda/sorta implicitly present here.
           |      It parametrizes the constructor template. C++ has no syntax
           |      for specifying it explicitly
           |
           This is `_Tp`, not `_Yp`. `_Tp` parametrizes 
           the whole `shared_ptr` template

_Tp int, . _Yp pii pair<int,int> , .

+4

Short-

, shared_ptr (). , .

Long-

shared_ptr, ( , ..). &pii->first int*, shared_ptr<int>, int&.

, , , : , , , . shared_ptr. ( ), . (, , , ), , .

, , :

#include <memory>
#include <utility>

using int_pair = std::pair<int, int>;

// Since this aliases a local variable, which goes out-of-scope
// immediately, dereferencing the variable will reference junk memory.
// It will also increment the shared_count of `p`, which may lead
// to a longer lifetime than desired.
// (This is obviously wrong, and that the point).
std::shared_ptr<int> temporary_reference(std::shared_ptr<int_pair>& p)
{
    int x = 5;
    return std::shared_ptr<int>(p, &x);
}


// Since this aliases a newly allocated variable, this will create a memory
// leak, since `new int(5)` will never be properly deleted.
// It will also increment the shared_count of `p`, which may lead
// to a longer lifetime than desired.
// (This is obviously wrong, and that the point).
std::shared_ptr<int> memory_leak(std::shared_ptr<int_pair>& p)
{
    return std::shared_ptr<int>(p, new int(5));
}


// This references an internal value in `p` and ties the lifetime
// of `p` to the aliased pointer, to ensure that deleting p
// does not invalidate the aliased pointer.
std::shared_ptr<int> aliased_value(std::shared_ptr<int_pair>& p)
{
    return std::shared_ptr<int>(p, &p->first);
}


int main()
{
    std::shared_ptr<int_pair> p(new int_pair(5, 3));
    auto i1 = temporary_reference(p);
    auto i2 = memory_leak(p);
    auto i3 = aliased_value(p);
    return 0;
}

&p->first, shared_ptr p, . aliasing , aliased shared_ptr.

, , , :

#include <memory>
#include <utility>

using int_pair = std::pair<int, int>;

int main()
{
    std::shared_ptr<int_pair> p(new int_pair(5, 3));
    int& i = p->first;
    p.reset();
    // the reference to i is no longer valid, 
    // since the shared count of the control block of `p` is now 0.
    // if we had used an aliased shared_ptr, it still would be valid

    return 0;
}
+1

Source: https://habr.com/ru/post/1694076/


All Articles