C++ 让共享\u ptr拥有现有指针的更简单方法

C++ 让共享\u ptr拥有现有指针的更简单方法,c++,c++11,memory,memory-management,shared-ptr,C++,C++11,Memory,Memory Management,Shared Ptr,许多程序员提倡使用make_shared,因为它可以减少键入和编程错误。然而,在某些情况下,使用shared\u ptr的构造函数是不可避免的。其中一种情况是,您希望拥有一个现有指针shared\u ptr,因为shared\u ptr(&existing\u ptr)是坏代码。相反,您必须使用笨拙的shared\u ptr(shared\u ptr(),p)。您不仅要重复自己,还必须创建一个临时对象 int main() { using namespace std; Foo

许多程序员提倡使用
make_shared
,因为它可以减少键入和编程错误。然而,在某些情况下,使用
shared\u ptr
的构造函数是不可避免的。其中一种情况是,您希望拥有一个现有指针
shared\u ptr
,因为
shared\u ptr(&existing\u ptr)
是坏代码。相反,您必须使用笨拙的
shared\u ptr(shared\u ptr(),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;
}

共享\u ptr
拥有一个现有指针有什么不那么详细的方法呢?

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

但这里有一种更简洁的方法,通过使用虚拟删除器来实现同样的效果:

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

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

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

您的使用不是预期的用途,而且相当危险,因为您已经隐式地创建了一个保证,即您传递给共享指针的数据将与共享指针或其副本的使用时间一样长,并且在任何有意义的意义上都无法强制执行该保证

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

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


只有当你俩都有一个坏掉的函数,无法修复它,并且在免费商店复制
Foo
过于昂贵,你的技术才值得尝试。无论如何,这应该是极端的情况。

&existing\u ptr
显然是错误的——你的意思是
和existing\u object
共享的\u ptr(&existing\u ptr)
根本不正确,但是
共享的\u ptr(existing\u ptr)有什么错呢
?@n.m.在这种情况下,
共享\u ptr
将尝试删除销毁时的指针,这会失败,因为指针没有指向分配了
new
@MMarkRansom的对象。对于无法删除的内容,需要共享\u ptr有什么意义?@n.m.不幸的是,有些人已经养成了在函数签名中使用它的习惯,迫使你在不合适的时候使用它。我同意,也没什么意义