删除std :: shared_ptr而不破坏托管对象?

时间:2015-03-08 02:40:52

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

我在以下情景中:

struct container {
    data* ptr;
};

void someFunc(container* receiver /* wants to be filled */) {
    auto myData = createData(); // returns shared_ptr<data>
    receiver->ptr = myData.get();
}

生成该数据的函数以及接收它的对象是两个不同库的一部分,我无法修改它的源代码。我必须使用这些数据类型,我无能为力。

所以我必须实现一个获取一些数据的函数,然后将指向该数据的指针传递给一个对象。我的问题是创建我的数据的函数返回一个shared_ptr实例。需要数据的对象只接受指向它的原始指针。

如您所见,我在get()上调用shared_ptr来获取原始指针并将其传递给接收对象。如果我没有弄错,那么只要shared_ptr超出范围,shared_ptr就会减少引用计数。所以在这种情况下,这意味着一旦函数返回它就会破坏我的数据,因为引用计数将达到0。

那么如何在不破坏托管对象的情况下摆脱shared_ptr实例呢?我将数据传递给的对象(为了简单起见,用&#34;容器&#34; struct说明)确实在其析构函数中处理内存清理,所以我不需要任何引用计数或类似的东西。我不想要任何东西来监视分配的数据了(除了接收指向它的指针的对象)。我想摆脱{{1}},只有一个指向已分配数据的原始指针,我可以将其传递给接收对象。

这可能吗?

4 个答案:

答案 0 :(得分:6)

static std::map m<data *, std::shared_ptr<data> >;

struct container {
    data* ptr;
};

void someFunc(container* receiver /* wants to be filled */) {
    auto myData = createData(); // returns shared_ptr<data>, I can't do anything about it
    receiver->ptr = myData.get();
    m[receiver->ptr] = myData;
}


void someOtherFunc(container* receiver)
{
  // delete receiver->ptr;
  m.erase(receiver->ptr);
}

通过地图延长了shared_ptr的生命。

答案 1 :(得分:2)

std::shared_ptr不会放弃所有权,因此您必须将其保留在类中的某个位置,以确保指针不会被删除。仍然,您可以使用获取的shared_ptr而不是存储原始指针。原始指针几乎总是一个糟糕的选择。

答案 2 :(得分:2)

这是不可能的。

即使您在container析构函数中处理对象破坏,也无法保证没有其他对象std::shared_ptr持有指向该对象的指针(在这种情况下,您将看到{{1} }错误)。

如果对象生命周期由double free管理(没有特殊删除器),那么您只能通过std::shared_ptrstd::shared_ptr来控制对象生存期。

答案 3 :(得分:1)

我能看到的唯一方法(如果你的设计允许)是包装你的容器:

struct container {
    data* ptr;
};

struct container_wrapper {
    std::shared_ptr<data> ptr; // ensure this lives as long as needed
    container cnt;
};

void someFunc(container_wrapper& receiver /* wants to be filled */) {
    receiver.ptr = createData();
    receiver.cnt.ptr = receiver.ptr.get();
}
相关问题