如果正在使用C++/CLI
C++/CLI已经有了try-finally,C++异常在.NET中被包装为SEHException,因此try-finally可以正常处理这些情况。
特别是ref class一定要使用到try-finally,因为ref class的析构函数需要使用delete运算符手动调用,系统是不会自动调用ref class的析构函数的。
<code class="language-cpp">// CLRConsoleApp1.cpp: 主项目文件。
#include "stdafx.h"
using namespace System;
ref class MyClass
{
public:
MyClass()
{
Console::WriteLine(L"MyClass()");
}
~MyClass()
{
Console::WriteLine(L"~MyClass()");
}
};
int main(array<system::string ^> ^args)
{
MyClass ^obj = gcnew MyClass();
try
{
// ...
}
finally
{
delete obj;
}
return 0;
}
</system::string></code>
如果正在使用纯C语言编写函数
可以使用__try-__finally这一组SEH,不过需要使用__leave正常离开这个范围避免回卷。这个功能是不允许在存在像std::string等C++栈对象的环境中使用的,否则会报错。
由于这种方法限制较多,不实用,因此并不推荐。
如果正在使用传统C++
传统C++中,一般使用析构函数保证异常资源释放,一般称之为RAII。
个人曾经比较反对RAII,原因是当时认为使用RAII意味着包装类型,而包装类型之后将会降低可迁移性。但其实使用RAII并不意味着非得包装类型,也可以只包装赋值和释放操作。
<code class="language-cpp">// main.cpp
#include <stdio.h>
struct StdioFileMgr
{
FILE *&f;
StdioFileMgr(FILE *&f, const char *fn, const char *md) : f(f)
{
f = fopen(fn, md);
}
StdioFileMgr(FILE *&f, const wchar_t *fn, const wchar_t *md) : f(f)
{
f = _wfopen(fn, md);
}
~StdioFileMgr()
{
if (f != NULL) fclose(f);
f = NULL;
}
};
int main()
{
{
FILE *f1 = NULL;
StdioFileMgr f1mgr(f1, "xxx.txt", "r");
// ...
}
return 0;
}
</stdio.h></code>
200字以内,仅用于支线交流,主线讨论请采用回复功能。