文件分配失败* class
assignment fails for a FILE* class
我试图将 class 包裹在 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 中不会写入任何内容
我什至在删除赋值过载后尝试过,因为我想默认行为应该是相同的,但问题仍然存在
如果我按预期使用原始 FILE*,它会工作 f.e
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 写对了,
file1 = file_ptr(L"text2",L"wb");
表达式创建一个临时 file_ptr
对象,然后 fptr = other.fptr;
复制临时对象拥有的 FILE
指针值。 Temp 对象立即被销毁并关闭文件指针,留下 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?
我试图将 class 包裹在 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 中不会写入任何内容
我什至在删除赋值过载后尝试过,因为我想默认行为应该是相同的,但问题仍然存在
如果我按预期使用原始 FILE*,它会工作 f.e
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 写对了,
file1 = file_ptr(L"text2",L"wb");
表达式创建一个临时 file_ptr
对象,然后 fptr = other.fptr;
复制临时对象拥有的 FILE
指针值。 Temp 对象立即被销毁并关闭文件指针,留下 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?