Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 共享ptr的子数据(类似子字符串?)_C++_Boost_Shared Ptr - Fatal编程技术网

C++ 共享ptr的子数据(类似子字符串?)

C++ 共享ptr的子数据(类似子字符串?),c++,boost,shared-ptr,C++,Boost,Shared Ptr,我有一个存储在共享\u ptr中的数据缓冲区 该缓冲区组织在几个封装层中,因此我最终得到: -----------------------------------... - Header 1 | Header 2 | Data -----------------------------------... (实际上,这是一个以太网数据包,我在其中一层接一层地解封) 读取头1后,我想将数据包的其余部分传递到下一层进行读取,因此我想创建一个指向以下内容的指针: -------------------

我有一个存储在
共享\u ptr
中的数据缓冲区

该缓冲区组织在几个封装层中,因此我最终得到:

-----------------------------------...
- Header 1 | Header 2 | Data
-----------------------------------...
(实际上,这是一个以太网数据包,我在其中一层接一层地解封)

读取头1后,我想将数据包的其余部分传递到下一层进行读取,因此我想创建一个指向以下内容的指针:

-----------------------...
- Header 2 | Data
-----------------------...
使用原始指针非常容易,因为这只是一个指针算术问题。但我如何通过共享的ptr实现这一点?(我使用boost::shared_ptr):

  • 我无法为“first shared_ptr.get()+offset”创建一个新的共享_ptr,因为仅获取头2+数据的所有权是没有意义的(删除最终会崩溃)
  • 我不想复制数据,因为这样做很愚蠢
  • 我希望两个对象之间共享整个缓冲区的所有权(即,只要父对象或只需要头2的对象需要数据,就不应删除数据)
我可以用类似于
boost::tuple
的结构来概括这一点,但我想知道是否有更方便/优雅的方法来实现这一结果


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

也许是这样的

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

    void* operator* () {
        offset += a_certain_length;
        return (shared_ptr<void>::operator*() + offset);
    }
};
类头文件夹:受保护的共享\ptr{
公众:
//建造师和诸如此类的废话
void*运算符*(){
偏移量+=某个长度;
返回(共享的ptr::运算符*()+偏移量);
}
};

我建议将每个层封装在一个类中,该类知道如何处理数据,就好像它就是那个层一样。将每一个视为缓冲区中的一个视图。这是一个让你思考的起点

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_;
};
类层1{
公众:
第1层(共享\u ptr缓冲区):缓冲区(缓冲区){}
/*将缓冲区视为第1层类型所需的所有函数*/
void DoSomething(){}
私人:
共享的ptr缓冲区;
};
班级第二层{
公众:
第二层(共享缓冲区):缓冲区(缓冲区){
/*将缓冲区视为第2层类型所需的所有函数*/
void DoSomethingElse(){}
私人:
共享的ptr缓冲区;
};
以及如何使用它:

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();
shared_ptr buff=getBuff();//<执行所需操作以获取原始缓冲区。
//我将它们一起展示,但很有可能,代码的各个部分只需要
//将数据视为属于某一层或另一层。
第1层l1(浅黄色);
第2层l2(浅黄色);
l1.DoSomething();
l2.DoSomethingElse();
通过这种方式布局,您可以编写只在该层上运行的函数,即使它们在内部表示相同的数据

但是,这绝不是完美的


也许Layer2应该能够调用Layer1的方法。因此,您也需要继承。我对你的设计了解不够,不能说这是否有用。另一个有待改进的地方是用一个类替换
共享的\u ptr
,该类具有处理缓冲区的有用方法。

顺便说一句,我只使用了一个简单的包装器,如果有人遇到这个问题,我会在这里复制它

类数据包装器{
公众:
数据包装器(共享数据、大小偏移、大小长度):mpData(pData)、mOffset(偏移)、MLENGHT(长度){}
void*GetData(){return(unsigned char*)mpData.get()+mOffset;}
//和康斯特一样。。。
void SkipData(size_t skipSize){mOffset+=skipSize;mllength-=skipSize;}
void GetLength常量{return mlLength;}
//然后可以添加运算符+、++=、(void*)、--=
//如果您需要类似指针的语义。
//另外,一个“memcpy”成员函数可以只复制这个缓冲区
//和其他辅助功能(如果需要)
私人:
共享ptr MPR数据;
尺寸t mOffset,最大长度;
};

使用GetData时要小心:确保在使用不安全的void*时不会释放缓冲区。只要知道DataWrapper对象是活动的,就可以安全地使用void*(因为它保存了缓冲区的共享ptr,因此它可以防止它被释放)。

好的,操作符*会在这里返回对
void
的引用,因此不适用。不过,我明白你的意思,这是以某种方式存储偏移量的想法(如我所说的元组,或者如你所说的在派生对象中。不过我更喜欢不侵入boost层次结构的想法,所以我宁愿避免从shared_ptr派生)。是的,问题是:Layer2不知道(如果我们不告诉它)头1的长度是多少(而且不应该在意)。它应该只看到从头2开始的缓冲区,你知道我的意思。所以我要么在第1层和第2层之间交换一些数据(例如,要跳过的偏移量),或者给第2层的指针已经偏移了。事实上,我只想要字符串::substr!!@Mic好的,我肯定会倾向于将
shared\u ptr
分解成更智能的东西,可以跟踪每一层在缓冲区中的起始位置。
Layer1
Layer2
可以将共享的ptr保存到而是在对象上。似乎您希望每个层都有单独的类型,同时有专门在单个层上操作的代码。我认为这种方法可以同时授予这两种类型。是的,因此两个层都保持相同的共享\u ptr,并使用“offset”变量来获取指针,如:smart.get()+偏移量。但它是反惯用的,因为它使用void*并且没有终身的保证。但我同意你的观点,我会这样说。我只是在检查是否有一些我不知道的神奇的东西。你可以保证终身至少包含共享指针的范围,这就是为什么每个级别都保持一个。如果在类外没有人持有原始指针(他们不应该持有,因为它是私有的)的情况下,您是安全的。我同意在共享的\u ptr上调用get()会有点伤害,我关心的是是否需要以安全的方式进行操作。