5

我现在正在破解旧的 C 代码,尝试使其更像 C++/Boost 风格:

有一个资源分配函数看起来像:

my_src_type* src;
my_src_create(&src, ctx, topic, handle_src_event, NULL, NULL);

我尝试用 shared_ptr 包装 src:

shared_ptr<my_src_type> pSrc;

我刚才忘了提。我需要这样做作为一个循环

std::map<string, shared_ptr<my_src_type>  > dict;
my_src_type* raw_ptr;

BOOST_FOREACH(std::string topic, all_topics)
{
    my_src_create(&raw_ptr, ctx, topic, handle_src_event, NULL, NULL);
    boost::shared_ptr<my_src_type> pSrc(raw_ptr);
    dict[topic] = pSrc;
}

我可以这样做吗?

4

6 回答 6

8

使用shared_ptrC 风格的资源

使用boost::shared_ptr,您可以将函数指针传递给“删除器”,当引用计数达到零时,该“删除器”将自动调用。此功能允许使用 shared_ptr 来管理遗留 C API 返回的资源。

考虑保持您的遗产my_src_create完好无损,并提供一个新的“工厂”函数,该函数返回一个shared_ptr

void my_src_deleter(my_src_type* raw_ptr)
{
    my_src_destroy(raw_ptr);
}

typedef boost::shared_ptr<my_src_type> my_src_shared_ptr;

my_src_shared_ptr create_my_src(...)
{
    my_src_type* raw_ptr;
    my_src_create(&raw_ptr, ctx, topic, handle_src_event, NULL, NULL);
    return my_src_shared_ptr(raw_ptr, &my_src_deleter);
}

std::map<string, my_src_shared_ptr> dict;

BOOST_FOREACH(std::string topic, all_topics)
{
    dict[topic] = create_my_src(ctx, topic, handle_src_event, NULL, NULL);
}

将传统 C 结构/函数包装在一个类中

或者,(如 jpalecek 建议的那样)您可以包装my_src在一个类中。遗留my_src对象的创建和销毁在构造函数和析构函数中处理。如果你打算这样做,你应该考虑你是否希望你的MySrc类是可复制的。如果MySrc创建重量级或成本高昂,您可能希望使其不可复制并考虑使用shared_ptr<MySrc>是否要共享所有权MySrc

class MySrc
{
public:
    typedef boost::shared_ptr<MySrc> Ptr;
    MySrc(...) { my_src_create(&src_, ...); }
    ~MySrc() { my_src_destroy(&src_); }
    // Other member functions that uses my_src legacy functions

private:
    my_src_type* src_;
    // Make copy-constructor and assignment private to disallow copies
    MySrc(const MySrc& rhs) {}
    MySrc& operator=(const MySrc& rhs) {return *this;}
};

std::map<string, MySrc::Ptr> dict;

BOOST_FOREACH(std::string topic, all_topics)
{
    dict[topic] = MySrc::Ptr(
        new MySrc(ctx, topic, handle_src_event, NULL, NULL) );
}

请注意,您还可以使用MySrc该类来包装对 my_src 实例进行操作的遗留函数。

如果您想要MySrc可复制,请确保实现复制构造函数和赋值运算符,以便执行深度复制。

于 2010-03-04T01:49:15.093 回答
2

不。

基本上,您必须以旧的 C 方式进行操作,然后以shared_pointer某种方式将结果转换为 a。

您可以通过简单地初始化 shared_pointer 来做到这一点

my_src_type* pSrc;
my_src_create(&src, ctx, topic, handle_src_event, NULL, NULL);
shared_ptr<my_src_type> sp(pSrc);

my_src_create但请注意,如果函数可以返回一个已经存在的对象,这将失败。此外,如果有一个my_src_destroy函数,它不会被调用。

恕我直言,最干净的方法是将结构包装在 C++ 类中:

class MySrc {
  my_src_type* pSrc;
public:
  MySrc(...) { my_src_create(&pSrc, ...); }
  ~MySrc() { my_src_destroy(&pSrc); }
private:
  MySrc(const MySrc&);
  void operator=(const MySrc&); // disallow copying
};

然后MySrc以通常的方式使用共享指针。

于 2010-03-03T13:21:48.373 回答
2

我认为你的问题没有多大意义。如果my_src_create正在返工,则传递对共享指针的引用,或者返回共享指针。如果您不修改该方法,那么您将无法真正做到。我建议使用原始指针进行创建,然后将其包装到共享指针中:

shared_ptr<my_src_type> src;
{
   my_src_type* raw_src;
   my_src_create(&raw_src, ctx, topic, handle_src_event, NULL, NULL);
   src.reset( raw_src ); // hand ownership to shared_ptr
}

获取共享指针内部的指针并对其进行修改会破坏共享指针不变量:您将更改指针但不会更新共享计数。

于 2010-03-03T13:21:49.277 回答
0

你也在返工my_src_create()吗?

给定函数的名称,我会返回一个 boost::shared_ptr 而不是传入一个预先构建的函数,因为这更清晰,恕我直言。除非该函数还返回某种失败/成功代码,但最好通过抛出异常来处理。

如果你非常想传入一个空的 shared_ptr,你可以通过非常量引用传入它并使用shared_ptr::reset()insidemy_src_create为其分配一个新值。

于 2010-03-03T13:14:54.317 回答
0

您始终可以“以旧方式”执行此操作,然后使用reset()make_shared()src将该指针分配给 shared_ptr 。

于 2010-03-03T13:17:48.170 回答
0

我将使用此代码来解决您的问题:

my_src_type* src;
my_src_create(&src, ctx, topic, handle_src_event, NULL, NULL);
boost::shared_ptr<my_src_type> pSrc(src);

从那时起,pSrc将管理 . 指向的分配内存my_src_type* src

编辑:删除我答案的错误部分。

于 2010-03-03T13:19:37.363 回答