【问题标题】:Passing raw data in C++在 C++ 中传递原始数据
【发布时间】:2011-09-08 14:12:35
【问题描述】:

到目前为止,每当我想将一些原始数据传递给函数(例如从缓冲区加载图像的函数)时,我都会这样做:

void Image::load(const char* buffer, std::size_t size);

今天我查看了 Boost 库,尤其是 property_tree/xml_parser.hpp 标头,我注意到了这个函数签名:

 template<typename Ptree> 
 void read_xml(std::basic_istream<typename Ptree::key_type::value_type>&, 
               Ptree &, int = 0);

这实际上让我很好奇:这是通过使用流在 C++ 中传递原始数据的正确方法吗?还是我误解了该函数的用途?

如果是前者,能否请您指出一些资源,我可以在其中学习如何为此使用流?我自己没有找到太多东西(主要是 API 参考),我也找不到 XML 解析器的 Boost 源代码。


编辑: 一些额外的细节

似乎对我想要什么有些困惑。给定一个数据缓冲区,如何将其转换为流,以使其与我在上面发布的read_xml 函数兼容?这是我的具体用例:

我正在使用SevenZip C library 从存档中读取 XML 文件。该库将为我提供一个缓冲区及其大小,我想将其放入流格式中,使其与read_xml 兼容。我怎样才能做到这一点?

【问题讨论】:

    标签: c++ stream


    【解决方案1】:

    嗯,流在 C++ 中被广泛使用,因为它们很方便:
    - 错误处理
    - 它们抽象出数据源,因此无论您是从文件、音频源还是相机中读取,它们都被视为输入流
    - 可能还有更多我不知道的优势

    以下是 IOstream 库的概述,也许它可以更好地帮助您了解流的情况: http://www.cplusplus.com/reference/iostream/

    了解它们的确切含义将帮助您了解如何以及何时使用它们。

    【讨论】:

      【解决方案2】:

      没有一种正确的方法来传递数据缓冲区。指针和长度的组合是最基本的方式;它是 C 友好的。传递流可能允许顺序/分块处理 - i。 e.不同时将整个文件存储在内存中。如果您想传递一个可变缓冲区(可能会增长),vector&lt;char&gt;&amp; 将是一个不错的选择。

      特别是在 Windows 上,可能会使用 HGLOBAL 或节对象句柄。

      C++ 哲学明确允许多种不同的样式,具体取决于上下文和环境。习惯就好。

      【讨论】:

        【解决方案3】:

        C++ 中的原始内存缓冲区可以是unsigned char* 类型,也可以创建std::vector&lt;unsigned char&gt;。您通常不想只使用 char* 作为缓冲区,因为标准不保证 char 使用单个字节中的所有位(即,这最终会因平台/编译器而异)。话虽如此,流也有一些出色的用途,考虑到您可以使用流从文件或其他输入等中读取字节,然后将这些数据存储在缓冲区中。

        【讨论】:

          【解决方案4】:

          似乎对我想要什么有些困惑。给定一个数据缓冲区,如何将其转换为流,使其与我上面发布的 read_xml 函数兼容?

          很容易(我希望PTree::Key_type::value_type 会类似于char):

          istringstream stream(string(data, len));
          read_xml(stream, ...);
          

          More on string streams here.

          【讨论】:

            【解决方案5】:

            这本质上是使用引用来传递流内容。所以在幕后,它本质上与你目前所做的非常相似,而且本质上是相同的——只是使用了不同的符号。简化后,引用只是隐藏了指针方面,因此在您的 boost 示例中,您实际上是在使用指向流的指针。

            引用具有避免所有引用/取消引用的优势,因此在大多数情况下更容易处理。但是,它们不允许您进行多级(取消)引用。

            以下两个示例函数的作用基本相同:

            void change_a(int &var, myclass &cls)
            {
                var = cls.convert();
            }
            
            void change_b(int *var, myclass *cls)
            {
                *var = cls->convert();
            }
            

            谈论传递的数据本身:这实际上取决于您要实现的目标以及更有效的目标。如果您想修改字符串,使用类std::string 的对象可能比使用指向缓冲区的经典指针(char *) 更方便。流的优势在于它们可以表示几种不同的事物(例如网络上的数据流、压缩流或简单的文件或内存流)。通过这种方式,您可以编写接受流作为输入的单个函数或方法,并且可以立即工作,而无需担心实际的流源。使用经典缓冲区执行此操作可能会更加复杂。另一方面,您不应该忘记所有对象都会增加一些开销,因此根据要完成的工作,指向字符串的简单指针可能非常好(并且是最有效的解决方案)。没有“唯一的方法”。

            【讨论】:

            • 不,我知道引用和指针。与裸数据缓冲区相比,Streams 似乎更好,因为您不必将它们的大小与它们一起传递(它们更安全)。我想知道如何创建这样的数据流,但是我在网上没有找到任何资源。
            • 您将它们的大小传递给它们 - 它只是隐藏在对象内部以及真实的数据/内容。你可以在 C 中做同样的事情,传递一个带有指针和长度的结构。要创建您自己的流,可以使用预定义的流类之一,或者创建您自己的派生类,实现您自己的不同成员方法的版本。
            猜你喜欢
            • 1970-01-01
            • 2014-02-07
            • 2011-08-02
            • 2021-03-13
            • 1970-01-01
            • 1970-01-01
            • 2011-06-03
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多