c++ - Google Protocol Buffer 和对任意二进制数据使用 std::string

标签 c++ stl binary-data

相关问题: 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/

相关文章:

c++ - 使用 C++/STL 将 std::vector<CString> 展平为 multi_sz 的推荐方法是什么

c++ - 哪种更好的方法可以对不同的数字进行排序?

c++ - 如何将二进制数据转换为整数值

c++ - 标准线程库与 Boost 相比如何?

c++ - Visual Studio 2010 中好的 C++ 主题的集合?

c++ - 如何在 Windows 上为 Dev-C++ 安装 C++ 库

c# - 二进制的最佳字符串表示

C++ - 这个条件语句写得正确吗?或者有没有更有效的写法?

C++ 模板 - 在元组及其类型的容器上进行模板化

java - 在java中打印带有空字符的字符串