许多程序员提倡使用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
拥有现有指针的简洁方法是什么?
答案 0 :(得分:6)
该构造函数的用途是允许共享指针指向共享指针的子对象。
您的使用不是预期用途,并且非常危险,因为您隐式创建了一个保证,即您传递给共享指针的数据将持续与共享指针或其副本一样长,然后无法在任何有意义的意义上强制执行该保证。
如果您将一个共享指针传递给一个函数,它有权利缓存一个副本,并在15分钟后使用它。如果您没有将共享指针传递给函数,则不需要一个。
通常,如果一个函数打算以难以预测的方式延长其参数的生命周期,那么它应该只需要一个共享指针。因此,如果你有一个带有共享指针的函数并且从不延长它的生命周期(或者指向它的指针的生命周期),它就不应该使用共享指针。问题在于你正在调用的函数,而不是你必须跳过箍来调用它。
只有当你们两个功能都被破坏时,和才能解决它和在免费商店上制作Foo
的副本过于贵,你的技术值得尝试。无论如何,这应该是极端的角落案例。
答案 1 :(得分:2)
IMO你在那里做什么不应该是很容易因为它非常危险,只有在高度专业化的情况下才需要两次输入类名应该是你担心的最少。
但是通过使用虚拟删除器,这是一种稍微简洁的方法来实现同样的目的:
auto ptr = std::shared_ptr<Foo>(&foo, [](void*){});
另外,在你的方法中,说ptr
拥有 foo
是不正确的。相反,它拥有空std::shared_ptr<Foo>
和指向 foo
的空对象(有关详细讨论,请参阅this answer)。在我上面的代码中它确实&#34;拥有&#34; foo
在某种技术意义上(或至少它认为它确实如此);当它的引用计数达到零时,它就被阻止对它做任何事情。