Stroustrup的RAII和演员操作符FILE*()=矛盾?

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在评论中提供的工作方式的有用链接:什么是"*这个的右值参考"?

  • @utnapistim那是['*this`的rvalue引用](http://stackoverflow.com/q/8610571/1364752). (7认同)
  • 这将禁止使用`fgetc(File_ptr("my_file"))`这可能有用 (3认同)

the*_*ill 7

由于经验的原因,思维从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)