0

に格納されているデータ バッファーがありshared_ptr<void>ます。

このバッファはいくつかのカプセル化されたレイヤーで構成されているため、最終的には次のようになります。

-----------------------------------...
- Header 1 | Header 2 | Data
-----------------------------------...

(実際には、レイヤーを次々にカプセル化解除するイーサネットパケットです)。

ヘッダー 1 を読み取ったら、残りのパケットを読み取りのために次のレイヤーに渡したいので、へのポインターを作成したいと思います。

-----------------------...
- Header 2 | Data
-----------------------...

ポインタ演算の問題になるだけなので、生のポインタを使用すると非常に簡単になります。しかし、 shared_ptr でそれを達成するにはどうすればよいですか? (私はboost::shared_ptrを使用しています):

  • 「最初のshared_ptr.get()+オフセット」に新しいshared_ptrを作成することはできません。所有権を取得するのは意味がないためですHeader 2 + Data(削除すると最終的にクラッシュします)
  • ばかげているので、データをコピーしたくありません
  • バッファ全体の所有権を2 つのオブジェクト間で共有する必要があります (つまり、親オブジェクトまたはヘッダー 2 のみを必要とするオブジェクトがデータを必要とする限り、データを削除しないでください)。

それを次のような構造にまとめることができますboost::tuple<shared_ptr<void>, int /*offset*/, int /*length*/>が、その結果を達成するためのより便利でエレガントな方法があるのではないかと思います。

ありがとう、

4

3 に答える 3

1

データをそのレイヤーであるかのように処理する方法を知っているクラスに、各レイヤーをカプセル化することをお勧めします。それぞれをバッファへのビューと考えてください。これがあなたに考えさせるための出発点です。

class Layer1{
public:
    Layer1(shared_ptr<void> buffer) : buffer_(buffer) { }

   /* All the functions you need for treating your buffer as a Layer 1 type */
    void DoSomething() {}

private:
   shared_ptr<void> buffer_;
};

class Layer2{
public:
    Layer2(shared_ptr<void> buffer) : buffer_(buffer) { }

   /* All the functions you need for treating your buffer as a Layer 2 type */
    void DoSomethingElse() {}

private:
   shared_ptr<void> buffer_;
};

そしてそれを使用する方法:

shared_ptr<void> buff = getBuff(); //< Do what you need to get the raw buffer.

// I show these together, but chances are, sections of your code will only need
// to think about the data as though it belongs to one layer or the other.
Layer1 l1(buff);
Layer2 l2(buff);

l1.DoSomething();
l2.DoSomethingElse();

このようにレイアウトすると、内部的に同じデータを表している場合でも、そのレイヤーでのみ動作する関数を記述できます。

しかし、これは決して完璧ではありません。

おそらく、Layer2はLayer1のメソッドを呼び出すことができるはずです。そのためには、継承も必要になります。あなたのデザインについて、それが役立つかどうかを言うのに十分なことはわかりません。他の改善の余地はshared_ptr<void>、バッファを処理するための便利なメソッドを持つクラスに置き換えることです。

于 2012-11-28T21:33:26.297 に答える
0

ちなみに、誰かが質問に出くわした場合にここで再現する単純なラッパーを使用しました。

class DataWrapper {
public:
    DataWrapper (shared_ptr<void> pData, size_t offset, size_t length) : mpData(pData), mOffset(offset), mLength(length) {}

    void* GetData() {return (unsigned char*)mpData.get() + mOffset;}
    // same with const...
    void SkipData (size_t skipSize) { mOffset += skipSize; mLength -= skipSize; }
    void GetLength const {return mLength;}

    // Then you can add operator+, +=, (void*), -, -=
    // if you need pointer-like semantics.
    // Also a "memcpy" member function to copy just this buffer may be useful
    // and other helper functions if you need

private:
    shared_ptr<void> mpData;
    size_t mOffset, mLength;
};

GetData を使用するときは注意してください。安全でない void* を使用している間は、バッファーが解放されないようにしてください。DataWrapper オブジェクトが有効であることがわかっている限り、void* を使用しても安全です (これは、バッファーへの shared_ptr を保持しているため、解放されないようにするためです)。

于 2012-12-20T13:43:42.027 に答える
0

シンプルなラッパーを使用できますか?

このようなものでしょうか?

class HeaderHolder : protected shared_ptr<void> {
public:
    // Constructor and blah blah

    void* operator* () {
        offset += a_certain_length;
        return (shared_ptr<void>::operator*() + offset);
    }
};
于 2012-11-28T21:08:40.107 に答える