Reputation: 855
The following (unsafe) code works
#include <iostream>
#include <fstream>
std::ofstream* create_unsafe_stream(const char* filename) {
return new std::ofstream {filename};
}
int main () {
std::ofstream& u_out = *create_unsafe_stream("foo.txt");
u_out << "foo\n" ;
delete &u_out;
return 0;
}
I tried to produce a safer version
#include <iostream>
#include <fstream>
#include <memory>
using stream_ptr = std::unique_ptr<std::ostream>;
stream_ptr create_safe_stream(const char* filename) {
return stream_ptr{ new std::ofstream {filename}};
}
int main() {
std::ostream& s_out = *create_safe_stream("foo.txt");
s_out << "foo\n" << std::endl;
return 0
}
Which compiles but, when I run it give me a segmentation fault. I was thinking that the problem is caused by the unique_ptr
going out of the scope. So I tried to modify a bit the main
to
int main() {
stream_ptr ofile = create_safe_stream("foo.txt");
std::ostream& s_out = *ofile;
s_out << "foo\n";
}
which works again.
Is there a way not to use an 'intermediate' variable like ofile
and doing all in a line?
The function create_safe_stream
is a toy model of what I want, that is this function may return either the std::ofstream
to that file or the std::cout
, so I think I really need to return a pointer to the base class std::ostream
. How can I do?
Upvotes: 3
Views: 1947
Reputation: 36503
Your assumption is correct. create_safe_stream
returns a std::unique_ptr
which immediately goes out of scope and thus the raw resource it holds is deleted
and trying to use it is UB.
The way to not use an intermediate variable and doing it all in one line is by just returning a std::ofstream
object instead:
std::ofstream create_safe_stream(const char* filename) {
return std::ofstream {filename};
}
int main() {
std::ostream s_out = create_safe_stream("foo.txt");
s_out << "foo\n" << std::endl;
return 0;
}
Upvotes: 3