相关问题: vector <unsigned char> vs string for binary data .
我的代码使用 vector<unsigned char>
对于任意二进制数据。但是,我的很多代码都必须与 Google 的 Protocol Buffer 代码接口(interface)。 Protocol Buffer 使用 std::string
对于任意二进制数据。这导致了很多丑陋的分配/复制/释放周期,只是为了在 Google Protocol Buffer 和我的代码之间移动数据。在很多情况下,我需要两个构造函数(一个接受 vector ,一个接受字符串)或两个函数来将函数转换为二进制有线格式。
代码在内部大量处理原始结构,因为结构是内容可寻址的(通过散列存储和检索)、签名等。所以这不仅仅是谷歌 Protocol Buffer 的接口(interface)问题。代码的其他部分也以原始形式处理对象。
我能做的一件事就是把我所有的代码都剪下来使用 std::string
对于任意二进制数据。我可以做的另一件事是尝试找出更有效的方法来将我的 vector 存储和检索到 Google Protocol Buffer 对象中。我想我的另一个选择是创建标准、简单但缓慢的字符串转换函数并始终使用它们。这将避免猖獗的代码重复,但从性能的角度来看会是最糟糕的。
有什么建议吗?我还缺少更好的选择吗?
这是我要避免的:
if(SomeCase)
{
std::vector<unsigned char> rawObject(objectdata().size());
memcpy(&rawObject.front(), objectdata().data(), objectdata().size());
DoSometingWith(rawObject);
}
当原始数据已经存在时,分配、复制、处理、释放完全没有意义。
最佳答案
我知道并看到有两种避免复制的方法。
传统的方式确实是传递一个指向已知实体的指针/引用。虽然这工作正常并且大惊小怪,但问题是它将您与给定的表示联系起来,这需要在必要时进行转换(如您所经历的)。
我用 LLVM 发现的另一种方式:
这个想法非常简单:两者都持有一个 T*
指向 T
数组的开头和一个 size_t
表示元素个数。
神奇的是它们完全隐藏了实际存储,无论是 string
, 一个 vector
,一个动态或静态分配的 C 数组……没关系。呈现的界面完全统一,无文案。
唯一需要注意的是它们不会取得内存的所有权(Ref
!),因此如果您不小心,可能会出现细微的错误。尽管如此,如果您仅在 transient 操作(例如,在函数内)中使用它们并且不存储它们以备后用,通常是没有问题的。
我发现它们在缓冲区操作中非常方便,特别是由于自由切片操作。范围比成对的迭代器更容易操作。
还有第三种方式我已经体验过,但直到现在还没有在正式的代码中使用过。这个想法是一个 vector<unsigned char>
是一个非常低级的表示。通过提高抽象层并使用,比方说,Buffer
类,就您的代码而言,您可以完全封装存储内存的确切方式,这样它就不是问题。
然后,随意选择一种需要较少转换的内存表示。
关于c++ - Google Protocol Buffer 和对任意二进制数据使用 std::string,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9373325/