我正在阅读一篇由于RAII之类的文章,你不再需要清理你的代码了.
促成这项研究的是我目前正在编写需要清理的东西才能退出该功能.
例如,我创建了一个文件,并映射了一个文件的视图.
通常,我只是使用goto或do {break;} while(false);退出.但是,C++ 11不再需要它吗?
不过了
if( fail ) {
UnmapViewOfFile(lpMapView);
CloseHandle(hFileMap);
CloseHandle(hFile);
}
Run Code Online (Sandbox Code Playgroud)
每几行代码?
一旦函数退出,编译器是否会自动将其包装起来?它似乎很难相信它实际上清理了文章所说的功能调用.(我可能会以某种方式误解它.)更可能的是,它只是通过从C++库调用它们的解构函数来清理创建的类库.
编辑:文章 - 来自维基百科:
这不一定表明它清理这些函数调用,但它确实意味着它为C++库函数的对象(如FILE *,fopen等对象)
它也适用于WinAPI吗?
C++标准肯定没有说明使用Windows API函数,如UnmapViewOfFile或CloseHandle.RAII是一种编程习惯,你可以使用或不使用它,它比C++ 11更老.
推荐使用RAII的原因之一是,在处理异常时,它可以使生活更轻松.析构函数将始终安全地释放任何资源 - 主要是内存,但也处理.对于内存,你在标准库中有类,比如unique_ptr和shared_ptr,还有vector和很多其他类.对于像WinAPI那样的句柄,你必须编写自己的句柄,如:
class handle_ptr {
public:
handle_ptr() {
// aquire handle
}
~handle_ptr() {
// release
}
}
Run Code Online (Sandbox Code Playgroud)
清理仍然是必要的,但由于可能存在异常,代码不应仅通过在函数结束时执行清理操作来进行清理.可能永远无法达到这一目的!代替,
在析构函数中进行清理.
在C++ 11中,在没有定义自定义类的情况下,在析构函数中进行任何类型的清理都非常容易,因为现在定义范围保护类变得更加容易.范围守卫是由Petru Marginean发明的,他与Andrei Alexandrescu在DDJ上发表了一篇关于它的文章.但是原始的C++ 03实现非常复杂.
在C++ 11中,一个简单的范围保护类:
class Scope_guard
: public Non_copyable
{
private:
function<void()> f_;
public:
void cancel() { f_ = []{}; }
~Scope_guard()
{ f_(); }
Scope_guard( function<void()> f )
: f_( move( f ) )
{}
};
Run Code Online (Sandbox Code Playgroud)
其中Non_copyable提供移动分配和移动构造,以及默认构造,但使复制分配和复制构造私有化.
现在,在成功获取某些资源之后,您可以声明一个Scope_guard对象,该对象将保证在范围的最后清理,即使面对异常或其他早期返回,例如
Scope_guard unmapping( [&](){ UnmapViewOfFile(lpMapView); } );
Run Code Online (Sandbox Code Playgroud)
附录:
我最好也应该提到标准库的智能指针 shared_ptr和unique_ptr,从而照顾指针的所有权,调用删除器时,业主人数变为0顾名思义,他们分别实现共享和独特的所有权.它们都可以将自定义删除器作为参数,但仅shared_ptr支持在将智能指针复制/移动到基类指针时使用原始指针值调用自定义删除器.
另外,我还应该更好地提到标准库容器类,特别是vector提供动态大小的可复制数组,具有自动内存管理,并且对于表示字符串string的特定用例数组提供了大致相同的功能char.这些类释放你不必直接处理new和delete,并获得这些细节的权利.
总而言之,
使用标准库和/或3 升时即可党的容器,
否则使用标准库和/或3 次聚会智能指针,
如果即使这样做并不能满足你的清理需求,也可以定义在析构函数中进行清理的自定义类.
| 归档时间: |
|
| 查看次数: |
666 次 |
| 最近记录: |