繁体   English   中英

为什么不能创建流缓冲区的副本?

[英]Why can't I create a copy of a stream buffer?

当我上这节课时:

class mystreambuf : public std::streambuf
{
public:
    mystreambuf(const std::streambuf& other) : std::streambuf(other)
    {
    }
};

可以编译,但是当我尝试执行此操作时,不会输出任何内容:

mystreambuf buf(*std::cout.rdbuf());
std::cout.rdbuf(&buf);

std::cout << "Hello";

如果bufcout buf的副本,那么为什么不打印任何内容?

流缓冲区的规范中没有任何内容说明如果您以此方式复制流缓冲区,则该副本将继续从同一设备进行读/写操作,也未指定cout使rdbuf()结果表现出您所希望的行为。

streambuf本质上是一个接口,它的副本构造函数实际上不会以某种方式调用实现该接口的任何类的副本构造函数。 多态类型不能按值保存,复制,传递等。 为了复制多态类型,您必须使用诸如virtual clone()成员函数之类的东西,并且streambuf接口不包含任何此类方法。

为了复制cout使用的streambuf,您必须使用其动态类型来访问它,即使那样也可能无法复制:例如,可能是多个访问同一设备的流缓冲区需要在其中进行协调或同步。某种方式,streambuf实现可能不允许复制,因此可以安全地避免必须进行同步。


我想做的是创建一个具有std :: cout的流缓冲区的所有特征的流缓冲区,但是内置了额外的成员函数(供我使用)。 你知道怎么做吗?

您想添加哪些额外的特征? 实现streambuf可能不是添加功能的适当位置。


如果要实现转发到预先存在的streambuf的streambuf接口的实现,则可以创建一个包含streambuf指针的streambuf类,将其正确地视为指向多态类型的指针,并通过将调用转发到内部来实现streambuf接口流缓冲。 这是一个非常简单的实现:

#include <iostream>

struct copiable_streambuf : std::streambuf {
    std::streambuf *buf; // non-owning pointer

    copiable_streambuf(std::streambuf *buf) : buf(buf) {}

    std::streambuf::int_type overflow(std::streambuf::int_type c) {
        buf->sputc(c);
        return 0;
    }
};

int main()
{
    copiable_streambuf buf (std::cout.rdbuf());
    std::ostream os(&buf);
    os << "Hello, World!\n";
}

您的示例代码涉及替换cout使用的缓冲区。 如果执行此操作,则应确保在程序结束时销毁cout之前将原始缓冲区放回原处,因为cout管理自己的流缓冲区的生存期,并且当cout的析构函数运行时,它可能需要它持有的流缓冲区是它最初创建的那个。

// RAII type for managing buffer switches.
struct buffer_switcher {
    std::ostream &os;
    std::streambuf *old;

    buffer_switcher(std::ostream &os, std::streambuf *buf)
        : os(os), old(os.rdbuf())
    {
        os.rdbuf(buf);
    }

    ~buffer_switcher() { os.rdbuf(old); }
};

int main() {
    // create our forwarding buffer
    copiable_streambuf buf(std::cout.rdbuf());

    // set up cout to use our buffer and simultaneously ensure that the buffer will get switched back as required
    buffer_switcher _(std::cout, &buf);

    std::cout << "Hello";    
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM