首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将流的缓冲区与nullptr交换以模拟移动?

将流的缓冲区与nullptr交换以模拟移动?
EN

Stack Overflow用户
提问于 2017-06-28 21:14:39
回答 1查看 237关注 0票数 1

我希望将std::istream存储在一个结构中,并且能够从另一个流构造它。目前,我有以下信息:

代码语言:javascript
复制
struct A {
    A(std::istream &in) : in_(in.rdbuf()) { }
protected:
    std::istream in_;
};

这只允许从已经创建的对象创建A类型的对象,但我希望能够:

代码语言:javascript
复制
A(std::stringstream("hello world!"));

我为std::istream添加了下面的rvalue-reference A重载

代码语言:javascript
复制
A(std::istream &&in) : in_(in.rdbuf()) {
    in.rdbuf(nullptr); // (1)
}

我添加了(1)以避免缓冲区在序列点之后被销毁,但我不知道是否定义了此行为,或者这是否真的有意义?

我可以像这样根据标准“移动”一个流缓冲区吗?如果不能,这是否适用于标准实现和流(std::stringstreamstd::fstream等)?

EN

回答 1

Stack Overflow用户

发布于 2017-06-28 22:01:50

最好避免与缓冲区打交道,让对象在内部为我们做这项工作。

我提出以下建议。有了模板,当我们将流移动到结构中时,我们可以确保构造一个完整类型的共享指针。

代码语言:javascript
复制
#include <sstream>
#include <iostream>
#include <fstream>
#include <memory>
#include <typeinfo>

struct A {
    template<typename T>
    A(T& is) : is{is}
    {
        std::cout << "Only taking a reference. Not taking ownership of std::istream.\n";
    }

    template<typename T>
    A(T&& is) : own_is{std::make_unique<T>(std::move(is))}, is{*own_is}
    {
        std::cout << "using move. Not sliced.\n";
    }

    void print_stream_type()
    {
        std::cout << typeid(is).name() << '\n';
    }
protected:
    std::unique_ptr<std::istream> own_is;
    std::istream& is;
};

int main()
{
    A a1{std::stringstream{"hello world!"}};

    A a2{std::cin};

    std::ifstream ifs{"input.txt"}; 
    A a3{ifs};

    A a4{std::ifstream{"input.txt"}};

    a1.print_stream_type();
    a2.print_stream_type();
    a3.print_stream_type();
    a4.print_stream_type();

}

MSVC2017上的输出:

代码语言:javascript
复制
using move. Not sliced.
Only taking a reference. Not taking ownership of std::istream.
Only taking a reference. Not taking ownership of std::istream.
using move. Not sliced.
class std::basic_stringstream<char,struct std::char_traits<char>,class std::allocator<char> >
class std::basic_istream<char,struct std::char_traits<char> >
class std::basic_ifstream<char,struct std::char_traits<char> >
class std::basic_ifstream<char,struct std::char_traits<char> >

还要注意,结构中成员的顺序很重要。如果A是通过引用构造的,则own_is变量将为空。但是如果我们传递一个rvalue,那么它将首先创建共享指针,然后取消对它的引用以传递有效的引用。在这两种情况下,指向流的引用都是相同的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44803572

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档