Reputation: 1335
Below are two pieces of code. One works, one does not, I'd like to know why. I apologise in advance for the lack of comments and awful variable names but right now this language is really grinding my gears.
// 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;
}
Upvotes: 1
Views: 510
Reputation: 19767
The std::[io]fstreams
in
and out
have local scope (or automatic storage duration) inside the TestWithStdIO
constructor. They are destroyed (and the files closed), along with their contained buffers, at the end of the function, leaving you with dangling pointers insidecin
and cout
.
Consider instead making in
and out
members of TestWithStdIO
, something like this:
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);
}
};
You might need in(inFile.c_str())
and the equivalent for out
if you only have C++03
support.
Also, as pointed out in the comments, there is no need to dynamically allocate the TestWithStdIO
instance, and in fact it is likely to be a source of bugs. Just do
TestWithStdIO ioTest ("in.txt", "out.txt");
Upvotes: 1
Reputation: 31657
In TestWithStdIO::TestWithStdIO()
, The stream buffer pointed to by in.rdbuf()
is destroyed together with in
(i.e. at the end of the constructor).
Upvotes: 1