Dav*_*vic 20 c++ pointers raii
我正在阅读Stroustrup的C++(3ed,1997),看看他是如何实现RAII的,在第365页我发现了这个:
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;}
};
Run Code Online (Sandbox Code Playgroud)
构造函数和析构函数的实现是显而易见的,并且符合RAII惯用法,但我不明白他为什么使用它operator FILE* () {return p;}.
这将导致以File_ptr下列方式使用:
FILE* p = File_ptr("myfile.txt", "r");
Run Code Online (Sandbox Code Playgroud)
结果是封闭的p,在这种情况下在语义上是不合适的.此外,如果File_ptr要用作RAII,则此运算符允许它像示例中那样被滥用.或者我错过了什么?
Mik*_*ail 28
似乎它是不可避免的邪恶价格的舒适.一旦你想要FILE*从你的花哨的RAII类中提取一种方法,它就会被误用.它是operator FILE*()或者FILE* getRawPtr()方法,或者其他什么,它可以在temporarty对象上调用,使结果在返回后立即无效.
但是,在C++ 11中,通过禁止对临时对象的调用,可以使其更加安全,如下所示:
operator FILE* () & { return p; }
// Note this -----^
Run Code Online (Sandbox Code Playgroud)
关于Morwenn在评论中提供的工作方式的有用链接:什么是"*这个的右值参考"?
由于经验的原因,思维从1997年起就已经发生了很大的变化,现在的一个主要建议是不要因为这样的问题而使用隐式演员.以前认为有一个隐式转换运算符可以更容易地改进现有代码,但是当函数破坏资源时会导致问题,因为RAII包装类不知道它.
现代约定是提供对底层指针的访问,但是给它一个名称,以便至少它是显式的.它不会捕捉到所有可能的问题,但可以更容易地查找潜在的违规行为.比如std::string它的c_str():
std::string myString("hello");
callFunctionTakingACharPointer(myString.c_str());
// however...
delete myString.c_str(); // there's no way of preventing this
Run Code Online (Sandbox Code Playgroud)