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すると、参照カウントがゼロになると自動的に呼び出される「deleter」に関数ポインタを渡すことができます。この機能により、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

いいえ。

shared_pointer基本的には、古いCの方法で実行してから、結果を何らかの方法で変換する必要があります。

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_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 に答える
0

いつでも「古い方法」で実行し、reset()またはmake_shared()srcを使用してそのポインタをshared_ptrに割り当てることができます。

于 2010-03-03T13:17:48.170 に答える
0

あなたもやり直していmy_src_create()ますか?

関数の名前を考えると、事前に構築されたものを渡すのではなく、boost::shared_ptr を返します。これは、IMHO がより明確でクリーンであるためです。関数が何らかの失敗/成功コードも返している場合を除きますが、例外をスローすることでより適切に処理できます。

どうしても空の shared_ptr を渡したい場合は、非 const 参照で渡し、shared_ptr::reset()内部で使用my_src_createして新しい値を割り当てることができます。

于 2010-03-03T13:14:54.317 に答える