shared_ptr的子数据(substring-like?)

时间:2012-11-28 21:01:50

标签: c++ boost shared-ptr

我有一个存储在shared_ptr<void>

中的数据缓冲区

这个缓冲区由几个封装的层组成,所以我最终得到:

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

(实际上它是一个以太网数据包,我依次解封层)。

一旦我读到Header 1,我想把剩下的数据包传递到下一层进行读取,所以我想创建一个指向的指针:

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

使用原始指针非常容易,因为它只是指针算术的问题。但是如何使用shared_ptr实现这一目标呢? (我使用boost :: shared_ptr):

  • 我无法创建新的shared_ptr到“first shared_ptr.get()+ offset”,因为将所有权仅仅Header 2 + Data(并且删除最终会崩溃)是没有意义的。
  • 我不想复制数据,因为它会很傻
  • 我希望整个缓冲区的所有权在两个对象之间共享(即,只要父对象或只需要Header 2的对象需要数据,数据就不应该被删除)。

我可以将它包装在像boost::tuple<shared_ptr<void>, int /*offset*/, int /*length*/>这样的结构中,但我想知道是否有更方便/更优雅的方法来实现这一结果。

谢谢,

3 个答案:

答案 0 :(得分: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>替换为具有处理缓冲区的有用方法的类。

答案 1 :(得分:0)

你能用一个简单的包装器吗?

这样的事可能吗?

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

    void* operator* () {
        offset += a_certain_length;
        return (shared_ptr<void>::operator*() + offset);
    }
};

答案 2 :(得分: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时要小心:确保在使用unsafe void *时不会释放缓冲区。只要知道DataWrapper对象是活动的就可以使用void *是安全的(因为它将shared_ptr保存到缓冲区,因此它可以防止它被释放)。

相关问题