【问题标题】:Creating an input stream from constant memory从常量内存创建输入流
【发布时间】:2012-10-15 01:49:32
【问题描述】:

我在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;

重要条件:不得以任何方式复制或更改数据(否则我只会使用字符串流。据我所知,不可能创建字符串流来自 const char 指针而不复制数据。)

【问题讨论】:

标签: c++ input stream


【解决方案1】:

唯一的方法是子类化 std::istream(这也需要子类化 std::streambuf)来创建您自己的从常量内存读取的流类。

这并不像听起来那么简单,因为 C++ 标准库流类非常混乱且设计糟糕。除非您需要大量扩展,否则我认为这不值得。

【讨论】:

    【解决方案2】:

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

    #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)) {
        }
    };
    

    唯一有点尴尬的是流缓冲区中的const_cast&lt;char*&gt;():流缓冲区不会更改数据但接口仍然需要使用char*,主要是为了更容易在“正常”流缓冲区。有了这个,你可以使用imemstream作为一个普通的输入流:

    imemstream in(data, size);
    in >> value;
    

    【讨论】:

    • @ildjarn:它定义了所有平台上的行为,而不是不同平台上的不同行为:std::stringbuf::setbuf() 是根据 27. 8.2.4 [stringbuf.virtuals] 第 15 段定义的实现。
    • 我正在基于此实现一些东西,但我真的需要一个有效的 tellg() / tellp() 用于包装 membuf 的任何 istream / ostream 实例。我已经看到一些迹象表明我需要实现seekoffseekpos,但没有可靠的工作示例来说明这一点。有什么见解吗?
    • @Andrew:代码没有分配任何内存,因此它没有释放任何内存。当 data 碰巧指向一个字符串文字时,这种变化是特别错误的。
    • @Andrew:分配data(如果已分配)的人负责释放它。由于代码 sn-p 没有显示数据的来源,它不应假设并做某事!代码显然不完整,因为没有声明 datasize。对于问题和答案,它们的来源并不重要,也不重要它们使用后会发生什么。
    • @Andrew:它违背了目的吗?简短的 sn-p 显示了实现该类的生产就绪版本所需的所有相关位。当然,代码的生产就绪版本附带文档、测试用例等。我认为答案不需要涵盖它使用的所有内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-24
    • 1970-01-01
    相关资源
    最近更新 更多