1

我为一个 C++ 类实现了一个 C-API,它使用其他对象的共享指针来访问它们。在我的 C-API 中,我当然只能得到原始指针。因此,我将 C-API 中的原始指针“转换”为共享指针,然后将其与我的 C++ 类方法一起使用:

method(std::shared_ptr<dataType>(raw-pointer));

现在我有一个问题,在“方法”的末尾总是调用共享指针析构函数,不幸的是它杀死了我的原始指针指向的对象(我不想要)。那么,如何防止原始指针被杀死?

我已经尝试过 reset() 或 swap() 之类的共享指针函数,但它们都没有让我的原始指针消失......

bool Traffic_doStep(traffic_handle t, environment_handle e, double cycletime) {
    if (!valid(t, __FUNCTION__)) return false;
    if (!valid(e, __FUNCTION__)) return false;
    if (!valid(cycletime, __FUNCTION__)) return false;

    try {
        t->doStep(std::shared_ptr<Environment>(e), cycletime);
        return true;
    }
    catch (const std::exception& e) {
        std::cerr << e.what() << std::endl;
        return false;
    }
}

预期的结果是原始指针 e 在此函数返回后仍指向有效对象。实际上,原始指针指向一个已删除的对象。

4

2 回答 2

12

不要将指针放在std::shared_ptr

C++ 中智能指针的目的是提供自动生命周期管理。当您编写std::shared_ptr<int> ptr{raw_ptr};时,期望是当ptr超出范围时,指向的对象raw_ptr将是delete'd。如果这不是意图,那么您不应该将指针放在智能指针中。

因此,如果您的应用程序不管理指针的生命周期,那么存储原始指针是完全可以接受的。

如果函数背后的 API 无法更改,您将需要构造一个std::shared_ptr带有无操作删除器的函数,以便在调用 clean-up 时,指针不会发生任何事情。

try {
    std::shared_ptr<Environment> temp_ptr{e, [](int *) {}/*No-Op Deleter*/};
    t->doStep(temp_ptr, cycletime);
    return true;
}

这将解决您的问题,但这当然是一个反模式;不要这样做,除非你已经被你无法控制的 API 设计约束所逼迫。

于 2019-08-14T15:18:05.267 回答
2

您可以提供共享指针的自定义删除器。

这是一个可行的构造函数:

template< class Y, class Deleter > 
shared_ptr( Y* ptr, Deleter d );

但我宁愿使用唯一的指针,然后释放它。

于 2019-08-14T15:21:31.617 回答