【问题标题】:Why does this code not switch cin and cout with file streams?为什么这段代码不使用文件流切换 cin 和 cout?
【发布时间】:2013-10-21 11:02:06
【问题描述】:

下面是两段代码。一个有效,一个无效,我想知道为什么。对于缺少 cmets 和糟糕的变量名,我提前道歉,但现在这种语言真的让我很吃力。

// File1.cpp (contains relevant includes)
// Works! It writes to out.txt and appears to use in.txt correctly
int main(int argc, char* argv[]) {
    int num;
    std::ifstream in("in.txt");
    std::streambuf* cinbuf = std::cin.rdbuf();
    std::cin.rdbuf(in.rdbuf());

    std::ofstream out("out.txt");
    std::streambuf* coutbuf = std::cout.rdbuf();
    std::cout.rdbuf(out.rdbuf());

    cout << "Give me a number: ";
    cin >> num;

    std::cin.rdbuf(cinbuf);
    std::cout.rdbuf(coutbuf);

    return 0;
}

// File2.cpp (contains relevant includes)
// Does not work! Outputs nothing to out.txt.
class TestWithStdIO {
        std::streambuf* cinbuf;
        std::streambuf* coutbuf;
    public:
        TestWithStdIO(const char* inFile, const char* outFile) {
            std::ifstream in(inFile);
            cinbuf = std::cin.rdbuf();
            std::cin.rdbuf(in.rdbuf());

            std::ofstream out(outFile);
            coutbuf = std::cout.rdbuf();
            std::cout.rdbuf(out.rdbuf());
        }
        ~TestWithStdIO() {
            std::cin.rdbuf(cinbuf);
            std::cout.rdbuf(coutbuf);
        }
};

int main(int argc, char* argv[]) {
    int num;
    TestWithStdIO* ioTest = new TestWithStdIO("in.txt", "out.txt");
    cout << "Give me a number: ";
    cin >> num;
    delete ioTest;

    return 0;
}

【问题讨论】:

  • inout 仅存在于构造函数调用中的堆栈上。一旦构造函数完成,它们就会“死亡”。也许也让它们成为成员变量(并将文件名传递给initializer list 以打开它们)。
  • @BoBTFish 您应该回答这个问题,因为它出了什么问题。 (嗯,他动态分配TestWithStdIO也是不对的。TestWithStdIO基本上是RAII,RAII和动态分配对我来说似乎是矛盾的。)
  • @JamesKanze 更不用说这样的原始指针不是异常安全的。
  • @BoBTFish 不错!太感谢了!让它成为一个答案,我会接受它:)
  • @syam 所以你会把它变成一个智能指针?管理 RAII 类的 RAII 类?几乎按照定义,不应动态分配 RAII 类。

标签: c++ ifstream cout cin ofstream


【解决方案1】:

std::[io]fstreams inoutTestWithStdIO 构造函数中具有本地范围(或自动存储持续时间)。在函数结束时,它们连同它们包含的缓冲区一起被销毁(并且文件关闭),在cincout 内留下悬空指针。

考虑改为使inout 成为TestWithStdIO 的成员,如下所示:

class TestWithStdIO {
        std::streambuf* cinbuf;
        std::streambuf* coutbuf;

        std::ifstream in_;  // <-- member
        std::ofstream out_; // <-- member
    public:
        TestWithStdIO(const std::string& inFile, const std::string& outFile) :
            in_(inFile), out_(outFile) // <-- initializer list
        {
            cinbuf = std::cin.rdbuf();
            std::cin.rdbuf(in_.rdbuf());

            coutbuf = std::cout.rdbuf();
            std::cout.rdbuf(out_.rdbuf());
        }
        ~TestWithStdIO() {
            std::cin.rdbuf(cinbuf);
            std::cout.rdbuf(coutbuf);
        }
};

如果您只有C++03 支持,您可能需要in(inFile.c_str())out 的等效项。

另外,正如 cmets 中所指出的,没有必要动态分配 TestWithStdIO 实例,实际上它很可能是 bug 的来源。做吧

TestWithStdIO ioTest ("in.txt", "out.txt");

【讨论】:

    【解决方案2】:

    TestWithStdIO::TestWithStdIO()中,in.rdbuf()指向的流缓冲区与in一起被销毁(即在构造函数的末尾)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-18
      • 2015-06-21
      • 2018-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多