【问题标题】:Create a boost::shared_ptr to an existing variable为现有变量创建 boost::shared_ptr
【发布时间】:2012-01-17 23:35:49
【问题描述】:

我有一个现有的变量,例如

int a = 3;

我现在如何创建boost::shared_ptra?例如:

boost::shared_ptr< int > a_ptr = &a; // this doesn't work

【问题讨论】:

  • 你为什么要这么做?
  • @curiousguy,我这样做的原因如下所述;我在堆栈上有一个变量,并且有一个需要共享点作为输入参数的函数。
  • 我想知道为什么函数需要shared_ptr
  • 啊哈 - 我正在使用点云库 (pointclouds.org),整个 API 旨在使用共享指针。

标签: c++ boost shared-ptr smart-pointers


【解决方案1】:

虽然您应该在创建它时将变量放入托管指针中,以便从现有指针中执行此操作。

int *a=new int;
boost::shared_ptr<int> a_ptr(a);

这就是说你绝对不想将堆栈变量放入 shared_ptr 会发生不好的事情

如果由于某种原因一个函数需要 shared_ptr 而你只有一个堆栈变量,你最好这样做:

int a=9;
boost::shared_ptr<int> a_ptr=boost::make_shared(a);

看这里:

http://www.boost.org/doc/libs/1_43_0/libs/smart_ptr/make_shared.html

同样值得注意的是,shared_ptr 在 c++11 标准中,如果你能够使用的话。您可以将 auto 与 make_shared 结合使用,就像构建演讲中的 Herb Sutter 笔记一样。

#include <memory>

int a=9;
auto a_ptr=std::make_shared(9);

【讨论】:

  • 那里,我把你的两个答案合并了。
  • 第一个建议真的很危险——当shared_ptr死亡时,它会删除指向的对象,即使原来的指针仍然存在。在这种情况下,您必须使用无操作删除器 - 请参阅 Luc Danton 的回答。
【解决方案2】:

首先,您有一个错误,因为shared_ptr 不会自动从适当类型的指针转​​换。您必须明确说明这是您想要做的:

int a = 3;
::boost::shared_ptr< int > a_ptr(&a); // DO NOT DO THIS!

你还有另一个问题。想象一下这段代码的效果:

int a = 3;
delete &a;

在我给出的第一个例子中,这将不可避免地发生,即使它不是那么直接。 shared_ptr 存在的全部原因是当所有指向它的指针消失时删除东西。当然,这会导致各种奇怪的行为。

你有两种方法来处理这个问题。一种是创建可以删除的内容。另一个是确保shared_ptr 实际上并没有删除它所指向的东西。各有利弊。

制作可以删除的东西:

优点:

  • 简单易行。
  • 您不必担心对象的生命周期。

缺点:

  • 有点慢,因为它会涉及一两个堆分配。
  • 生成的shared_ptr 将引用一个副本,因此对a 的修改不会反映在它所指向的事物的值中。

怎么做:

::boost::shared_ptr<int> a_ptr(::boost::make_shared(a));

这非常类似于(这也可以):

::boost::shared_ptr<int> a_ptr(new int(a));

但它的效率略高。 ::boost::make_shared 做了一些魔术来分配引用计数和连续内存中的对象,从而节省了对分配器的调用并提高了引用的局部性。

使shared_ptr 实际上不会删除它所指向的内容:

优点:

  • 更快,尽管它仍然涉及为引用计数分配堆
  • 直接解决手头的问题(您指向的内容无法删除)。
  • shared_ptr 指的是a,因此如果您更改它的值,通过指针访问它的东西将看到新值。

缺点:

  • 需要更多地了解shared_ptr 的工作原理,这意味着阅读您代码的人也必须知道。
  • 如果您指向的对象在所有指向它的shared_ptr 之前超出范围,那么这些指针就会悬空,这很糟糕。
  • 前一点使这是一个非常冒险的解决方案。我通常会避免它。

怎么做:

函数之外的某个地方(可能在匿名命名空间中):

void do_nothing_deleter(int *)
{
    return;
}

然后在函数中:

int a = 3;
::boost::shared_ptr a_ptr(&a, do_nothing_deleter);

【讨论】:

    【解决方案3】:

    你写的不行,因为你要找的shared_ptr的构造函数是explicit,所以你需要这样写

    boost::shared_ptr<int> a_ptr(&a); // Don't do that!
    

    那个的问题在于,delete 将在a_ptr 的存储值上被调用。由于在您的示例中 a 具有自动存储持续时间,因此这非常糟糕。所以我们也传入了一个自定义删除器:

    boost::shared_ptr<int> a_ptr(&a, noop_deleter);
    

    noop_deleter 的 C++11 实现:

    auto noop_deleter = [](int*) {};
    

    C++03版本:

    // Can't be put in local scope
    struct {
        void
        operator()(int*) const
        {}
    } noop_deleter;
    

    【讨论】:

    • 这是一个非常棒的知识。我认为其他人的make_shared 想法更容易应对,但我真的认为这是最好的答案。
    • @Omnifarious:这是唯一 正确 的答案,因为问题是关于创建 shared_ptr 到 existing 变量,而不是它的副本.同时将noop_deleter 设为模板会更好。
    • 虽然这是一条有趣的信息,但我强烈建议不要这样做。使用 shared_ptr 的事实是因为您不知道对象何时会被销毁。但是,您知道对象将在堆栈​​上持续多长时间。因此,即使您确切知道它何时会销毁,也没有必要这样做,因为您始终可以分配回堆栈变量。
    • @111111:有利有弊。这种方法运行的巨大风险是shared_ptr 不会在堆栈变量之前消失。但它比在堆上创建副本更有效。 ybungalobill 是正确的,这是对所述问题的唯一技术正确答案。它不值得被否决。
    • @Omnifarious 嗯,很公平,事后看来,我也许不应该投反对票。但是创建一个 shared_ptr 来堆栈变量是有风险的事情。如果您确切知道变量需要多长时间,您可能不会使用 shared_ptr。因为他知道他希望它持续多长时间(即当它包含他的答案时,他可以重新分配给堆栈变量。) - 如果你编辑答案,我会收回反对票。
    【解决方案4】:

    您不能为现有变量创建 boost::shared_ptr。存储在 boost::shared_ptr 中的项目在创建时存储。

    但是,您可以创建一个 boost::shared_ptr 作为现有变量的副本。

    例如

    int a = 3; // Existing variable
    boost::shared_ptr<int> aCopy = boost::make_shared<int>(a); //Create copy with value of a
    

    请注意,您需要为 make_shared 添加&lt;boost/make_shared.hpp&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-26
      • 2021-10-10
      • 2013-07-09
      • 1970-01-01
      • 2023-03-05
      • 1970-01-01
      • 2013-09-24
      • 1970-01-01
      相关资源
      最近更新 更多