FILE *类的赋值失败

时间:2017-09-23 13:16:19

标签: c++ file class raii

我试图将类包装在FILE *周围,这里是

class file_ptr
{
    public:
        file_ptr(const wstring& _FileN, const wstring& _OpenMode) : file_n(_FileN), omode(_OpenMode),
        fptr(_wfopen(file_n.c_str(), omode.c_str()))
        {
            if (!fptr)
                throw wstring(L"Failed to open File ") + _FileN;
        }

        ~file_ptr()
        {
            fclose(fptr);
        }

        file_ptr& operator =(const file_ptr& other)
        {
            if (this != &other)
            {
                this->~file_ptr();
                fptr = other.fptr;
                file_n = other.file_n; omode = other.omode;
            }
        }

        operator FILE* () { return fptr; }

    private:
        wstring file_n, omode;
        FILE* fptr;
};

为什么是wstring?我需要Unicode支持。

现在问题可以说它做了类似的事情

int main() {
    try {
        file_ptr file1(L"text1",L"wb");
        fwrite("Hello",1,5,file1);
        file1 = file_ptr(L"text2",L"wb");
        fwrite("Hello",1,5,file1);
    } catch ( const wstring& e ) {
        wcout << e << endl;
    }
    return 0;
}

任何内容都不会写在text2

我甚至在删除我的赋值重载后尝试过,becoz我认为默认行为应该相同,但问题仍然存在

如果我按原样使用原始文件*,那么它是有效的。

int main() {
    try {
        FILE* file1 = _wfopen(L"text1",L"wb");
        fwrite("Hello",1,5,file1);
        fclose(file1);
        file1 = _wfopen(L"text2",L"wb");
        if (!(file1))
            throw L"Can't open file";
        fwrite("Hello",1,5,file1);
    } catch ( const wstring& e ) {
        wcout << e << endl;
    }
    return 0;
}

text2写得正确,

1 个答案:

答案 0 :(得分:3)

file1 = file_ptr(L"text2",L"wb");表达式创建临时file_ptr对象,然后fptr = other.fptr;复制临时对象拥有的FILE指针值。临时对象立即被销毁,并关闭文件指针,使用file1指针离开FILE。您应该编写一个移动赋值运算符:

file_ptr &
operator =(const file_ptr & other) = delete; // prevent accidental use

file_ptr &
operator =(file_ptr && other) noexcept
{
    if(this == ::std::addressof(other))
    {
        ::std::terminate(); // there is no context when selfassignment makes sense
    }
    //this->~file_ptr(); calling destructor on itself is no good
    ::fclose(this->fptr);
    this->fptr = other.fptr;
    other.fptr = 0;
    this->file_n = ::std::move(other.file_n);
    this->omode = ::std::move(other.omode);
    return(*this);
}

正如评论中所提到的,禁用复制构造函数并实现移动构造函数以防止在构造期间发生类似问题是一个好主意。您可能还想查看Rule-of-Three becomes Rule-of-Five with C++11?