【问题标题】:Initialize member istream from either existing istream or from one created by class itself从现有 istream 或类本身创建的 istream 初始化成员 istream
【发布时间】:2017-10-29 00:37:08
【问题描述】:

我试图弄清楚如何拥有一个成员变量,它要么代表传入的 istream,要么代表类自己创建的成员变量。

我认为如果我动态分配类创建的istream,则使用指向istream 的指针可以工作;但是,问题在于unique_ptr 将尝试释放非动态分配的内存。

这里有一些代码可以重现我遇到的问题:

#include <iostream>
#include <fstream>
#include <memory>
#include <string>

class example {
public:
  explicit example(std::istream& i)
    : m_input(&i)
  {}
  explicit example(const std::string& path)
    : m_input(new std::ifstream(path))
  {}
private:
  std::unique_ptr<std::istream> m_input;
};

int main() {
  example e1(std::cin);
  example e2("./test.txt");
}

e1 将尝试释放 std::cin,这会导致错误。我知道我可以使用多个成员,例如

#include <iostream>
#include <fstream>
#include <memory>
#include <string>

class example {
public:
  explicit example(std::istream& i)
    : m_i(),
      m_input(&i)
  {}
  explicit example(const std::string& path)
    : m_i(path),
      m_input(&m_i)
  {}
private:
  std::ifstream m_i;
  std::istream *m_input;
};

int main() {
  example e1(std::cin);
  example e2("./test.txt");
}

但我想知道是否有一种方法可以只使用一个成员变量

【问题讨论】:

  • 流不可复制?我错过了你的问题吗?
  • @πάνταῥεῖ 对,它们是不可复制的,所以我需要一个成员,它是指针或对传入流的引用。但是,这与我创建自己的流的构造函数发生冲突,因为如果我想使用相同的成员变量(它是一个指针),我必须动态分配。这样做的问题是我只在字符串构造函数中动态分配指针,因此,当我尝试解除分配时,如果example 是从现有的istream 构造的,那将是一个错误。有意义吗?
  • 不,这些东西没有意义,抱歉。请详细说明您的用例和您真正想要解决的问题。
  • @πάνταῥεῖ 好吧,如果我不清楚,对不起。我有一个需要从输入流中读取的类。我的目标是我希望能够从现有输入流或文件路径初始化该类的输入流。
  • 为什么你需要使用文件路径的构造函数呢?如果只是为了方便,我会删除它以保持接口和实现简单。 example 类的用户已经可以创建 std::ifstream(可以从文件路径构造)并将其传递给 example 类。

标签: c++ file c++11 pointers memory


【解决方案1】:

我猜你可能会通过存储指向流的指针来扩展你的方法:

class X {
    public:
        explicit X(std::istream& stream)
            : stream(&stream, [](std::istream* stream){})
        {}

        explicit X(const std::string& path)
            : stream(new std::ifstream(path),
                [](std::istream* stream) { delete stream; })
        {}

    private:
        using StreamDeleter = std::function<void(std::istream* stream)>;

        std::unique_ptr<std::istream, StreamDeleter> stream;
};

只需添加一个自定义删除器。在现有流的情况下,它什么也不做。相反,如果流是手动创建的,它会释放流。

【讨论】:

  • 我正要回答这个方向。 +1
  • 非常感谢!既然您已经回答了我关于它是否可以完成的假设问题,您认为我应该应该这样做吗?与只有一个额外的成员相比,这似乎相当复杂。
  • @AR7 我想添加一个额外的成员不是最好的选择。使用自定义删除器,您可能拥有更灵活的解决方案。我的意思是为不同的情况添加新成员会使设计变得很尴尬。同时,您可能会避免它并且只有一个成员知道如何正确释放资源(流)。
猜你喜欢
  • 1970-01-01
  • 2015-09-14
  • 2016-10-01
  • 2010-10-12
  • 2016-09-17
  • 1970-01-01
  • 2014-04-08
  • 2023-03-06
  • 2011-02-23
相关资源
最近更新 更多