我有一个存储在shared_ptr<void>
。
这个缓冲区由几个封装的层组成,所以我最终得到:
-----------------------------------...
- Header 1 | Header 2 | Data
-----------------------------------...
(实际上它是一个以太网数据包,我依次解封层)。
一旦我读到Header 1,我想把剩下的数据包传递到下一层进行读取,所以我想创建一个指向的指针:
-----------------------...
- Header 2 | Data
-----------------------...
使用原始指针非常容易,因为它只是指针算术的问题。但是如何使用shared_ptr实现这一目标呢? (我使用boost :: shared_ptr):
Header 2 + Data
(并且删除最终会崩溃)是没有意义的。我可以将它包装在像boost::tuple<shared_ptr<void>, int /*offset*/, int /*length*/>
这样的结构中,但我想知道是否有更方便/更优雅的方法来实现这一结果。
谢谢,
答案 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保存到缓冲区,因此它可以防止它被释放)。