让shared_ptr拥有现有指针的更简单方法

Easier way to have shared_ptr own an existing pointer

本文关键字:指针 更简单 方法 shared ptr 拥有      更新时间:2023-10-16

许多程序员提倡使用make_shared,因为它减少了类型并减少了编程错误。然而,在某些情况下,使用shared_ptr的构造函数是不可避免的。其中一种情况是,您有一个现有的指针,希望shared_ptr拥有它,因为shared_ptr<Foo>(&existing_ptr)是坏代码。相反,您必须使用笨重的shared_ptr<Foo>(shared_ptr<Foo>(), p)。你不仅在重复自己,而且还必须创建一个临时对象。

int main()
{
    using namespace std;
    Foo foo;
    foo.n = 1;
    {
        auto ptr = make_shared<Foo>(move(foo));
        ptr->n = 42;
        cout << ptr->n << " " << foo.n << 'n';
    }
    {
        auto p = &foo;
        auto ptr = shared_ptr<Foo>(shared_ptr<Foo>(), p);
        ptr->n = 42;
        cout << ptr->n << " " << foo.n << 'n';
    }
    return 0;
}
Foo::Foo()
Foo::Foo(Foo &&)
42 1
Foo::~Foo()
42 42
Foo::~Foo()

shared_ptr拥有现有指针的一种不那么冗长的方法是什么?

该构造函数的预期用途是允许共享指针指向共享指针的子对象。

您的使用不是预期用途,而且非常危险,因为您已经隐式地创建了一个保证,即传递给共享指针的数据将与共享指针或其副本一样持续,然后却未能在任何有意义的意义上强制执行该保证。

如果您将一个共享指针传递给一个函数,它完全有权缓存一个副本,并在15分钟后使用它。如果您不向函数传递共享指针,则不需要。

通常,如果函数打算以难以预测的方式延长其参数的生存期,则只应要求共享指针。因此,如果您有一个函数使用共享指针,并且从不延长其生存期(或指向它的指针的生存期),那么它不应该使用共享指针。问题在于你调用的函数,而不是你必须如何跳过重重关卡才能调用它

只有当你们两个都有一个功能坏了,都无法修复并且在免费商店上复制Foo过于昂贵时,你的技术才值得尝试。无论如何,这应该是极端的情况。

IMO你在那里做的事情不应该很容易,因为这非常危险,而且只有在高度专业化的情况下才有必要,在这种情况下,键入两次类名应该是你最不担心的。

但这里有一种稍微简洁一点的方法,可以通过使用伪deleter来实现同样的目的:

auto ptr = std::shared_ptr<Foo>(&foo, [](void*){});

此外,在您的方法中,说ptr拥有foo是不正确的;相反,它在空的std::shared_ptr<Foo>中拥有null对象,并且指向foo(有关更长的讨论,请参阅此答案)。在我上面的代码中,它确实在某种技术意义上"拥有"foo(或者至少它认为自己拥有);当它的引用计数达到零时,它被阻止对它做任何事情。