从常量内存创建输入流

23 c++ input stream

我在const char*指针指向的缓冲区中有一些数据.数据只是一个ASCII字符串.我知道它的大小.我希望能够以与从流中读取数据相同的方式读取它.我正在寻找一个允许我编写如下代码的解决方案:

// for example, data points to a string "42 3.14 blah"
MemoryStreamWrapper in(data, data_size);
int x;
float y;
std::string w;
in >> x >> y >> w;
Run Code Online (Sandbox Code Playgroud)

重要条件:不得以任何方式复制或更改数据(否则我只使用字符串流.据我所知,不能在不复制数据的情况下从const char指针创建字符串流. )

Die*_*ühl 38

这样做的方法是创建一个合适的流缓冲区.例如,这可以这样做:

#include <streambuf>
#include <istream>

struct membuf: std::streambuf {
    membuf(char const* base, size_t size) {
        char* p(const_cast<char*>(base));
        this->setg(p, p, p + size);
    }
};
struct imemstream: virtual membuf, std::istream {
    imemstream(char const* base, size_t size)
        : membuf(base, size)
        , std::istream(static_cast<std::streambuf*>(this)) {
    }
};
Run Code Online (Sandbox Code Playgroud)

唯一有点尴尬的是const_cast<char*>()在流缓冲区中:流缓冲区不会改变数据但是仍然需要char*使用接口,主要是为了更容易在"普通"流缓冲区中更改缓冲区.有了这个,您可以imemstream用作普通输入流:

imemstream in(data, size);
in >> value;
Run Code Online (Sandbox Code Playgroud)

  • 我正在实现基于此的东西,但我真的需要一个工作`tellg()`/`tellp()`用于包装`membuf`的任何`istream` /`ostream`实例.我已经看到了一些迹象表明我需要实现`seekoff`和`seekpos`,但是没有可行的实例.任何见解? (5认同)
  • @Andrew:代码没有分配任何内存,因此它不会释放任何内存.当`data`碰巧指向字符串文字时,更改特别错误. (3认同)
  • @Andrew:我很困惑 - 什么课程是“不熟悉的”?`std::streambuf` 是这里唯一的基类,显然它是一个标准类(因此有 `std::` 前缀)。怎么这么陌生?出于查看内存的目的,从类中读取内容完全符合其预期目的。...就像例子一样。如果您不喜欢这个答案,请随时投反对票和/或创建您自己的答案。 (3认同)
  • @Andrew:在 2017 年,仅通过传递原始指针来传递缓冲区的所有权并不是一个好主意。在这种情况下,您只需传递 std::unique_ptr&lt;char&gt; &amp;&amp; 。传递原始 const ptr 表明您不传递所有权,至少在 2017 年的代码中是这样。 (3认同)
  • @ildjarn:它在所有平台上定义了行为,而不是在不同平台上的不同行为:`std :: stringbuf :: setbuf()`是根据27定义的实现.8.2.4 [stringbuf.virtuals]第15段. (2认同)
  • 在使用时,将其放在C ++ 15中。 (2认同)
  • @MooingDuck:上周我了解到我们目前正在瞄准C++ 2014!也就是说,准备进入工作文件的完整提案将在4月份被要求 - 虽然它是一个小而实际有用的功能,但我不认为这种情况会发生.一个绊脚石是,每当IOStreams出现任何事情时,都会有这样一个重大的呻吟:"我们能不能拥有更好的东西?" 但没有人提出更好的东西...... (2认同)
  • @Andrew:分配`data`(如果已分配)的人负责释放它。由于代码片段未显示数据来自何处,因此不应假设并执行某些操作!代码显然不完整,因为没有声明 `data` 或 `size`。对于问题和答案,这些的来源并不重要,它们被使用后会发生什么也不重要。 (2认同)
  • @安德鲁:是否达到目的?简短的代码片段显示了实现该类的生产就绪版本所需的所有相关位。当然,该代码的生产就绪版本随附文档,测试用例等。我认为答案无需涵盖其使用的所有内容。 (2认同)
  • 介意我们通过`seekpos`和`seekoff`的实现来扩展这个答案吗?我花了一段时间才找到正确的方法,并可以帮助其他寻找相同方法的人。 (2认同)