I was reading through Stroustrup’s C++ (3ed, 1997) to see how he implemented the RAII, and on page 365 I found this:
class File_ptr{
FILE* p;
public:
File_ptr(const char* n, const char* a){p = fopen(n, a);}
File_ptr(FILE* pp) { p = pp; }
~File_ptr() {fclose(p);}
operator FILE* () {return p;}
};
The implementation of constructors and destructors is obvious and complies with the RAII idiom, but I don’t understand why he uses the operator FILE* () {return p;}
.
This would result in using File_ptr
in the following way:
FILE* p = File_ptr("myfile.txt", "r");
The result in a closed p
, which is semantically inappropriate in this case. Also, if File_ptr
is meant to be used as RAII, this operator allows it to be misused like in the example. Or am I missing something?
Seems like it is inevitable evil price for comfort. Once you want a way FILE*
be extractible from your fancy RAII class, it can be misused. Will it be operator FILE*()
or FILE* getRawPtr()
method, or whatever, it can be called on a temporarty object, making the result invalid just after it is returned.
In C++11, however, you can make this a little more secured, by disallowing this call on temporaries, like this:
operator FILE* () & { return p; }
// Note this -----^
Useful link on how it works provided by Morwenn in the comments: What is "rvalue reference for *this"?