【问题标题】:How is this shared_ptr automatically converted to a raw pointer?这个 shared_ptr 如何自动转换为原始指针?
【发布时间】:2019-06-22 09:16:09
【问题描述】:

我现在正在学习 C++11 的enable_shared_from_this;一个例子让我很困惑:shared_from_this() 返回的shared_ptr 类型如何转换为这个原始指针?

#include <iostream>
#include <memory>
#include <functional>

struct Bar {
    Bar(int a) : a(a) {}
    int a;
};

struct Foo : public std::enable_shared_from_this<Foo> {
    Foo() { std::cout << "Foo::Foo\n"; }
    ~Foo() { std::cout << "Foo::~Foo\n"; }

    std::shared_ptr<Bar> getBar(int a)
    {
        std::shared_ptr<Bar> pb(
            new Bar{a}, std::bind(&Foo::showInfo, shared_from_this(), std::placeholders::_1)
        );
        return pb;
    }

    void showInfo(Bar *pb)
    {
        std::cout << "Foo::showInfo()\n";
        delete pb;
    }

};

int main()
{
    std::shared_ptr<Foo> pf(new Foo);
    std::shared_ptr<Bar> pb = pf->getBar(10);
    std::cout << "pf use_count: " << pf.use_count() << std::endl;
}

【问题讨论】:

    标签: c++ c++11 c++-standard-library


    【解决方案1】:

    这是 std::bind 聪明,而不是指针。

    如 Callable 中所述,当调用指向非静态成员函数的指针或指向非静态数据成员的指针时,第一个参数必须是引用或指针(可能包括智能指针,例如 std::shared_ptr和 std::unique_ptr) 到其成员将被访问的对象。

    bind 已实现,因此它可以接受智能指针来代替原始指针。

    你可以在glibc++ implementation than bind internally calls invoke看到:

      // Call unqualified
      template<typename _Result, typename... _Args, std::size_t... _Indexes>
    _Result
    __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>)
    {
      return std::__invoke(_M_f,
          _Mu<_Bound_args>()(std::get<_Indexes>(_M_bound_args), __args)...
          );
    }
    

    std::invoke 可以开箱即用地处理智能事物(指针、reference wrappers 等):

    INVOKE(f, t1, t2, ..., tN)定义如下:

    如果f是一个指向类T的成员函数的指针:

    • 如果std::is_base_of&lt;T, std::decay_t&lt;decltype(t1)&gt;&gt;::value 为真,则INVOKE(f, t1, t2, ..., tN) 等价于(t1.*f)(t2, ..., tN)
    • 如果std::decay_t&lt;decltype(t1)&gt;std::reference_wrapper 的特化,那么INVOKE(f, t1, t2, ..., tN) 等价于(t1.get().*f)(t2, ..., tN)
    • 如果t1不满足前面几项,那么INVOKE(f, t1, t2, ..., tN)等价于((*t1).*f)(t2, ..., tN)

    【讨论】:

    • 非常感谢,我找到原因了,这是std::invoke()的规则。第一个参数并不总是这个原始指针,可能是引用或智能指针。
    猜你喜欢
    • 1970-01-01
    • 2021-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-07
    • 1970-01-01
    相关资源
    最近更新 更多