在C++中不再需要清理代码吗?

Jas*_*son 2 c++ c++11

我正在阅读一篇由于RAII之类的文章,你不再需要清理你的代码了.

促成这项研究的是我目前正在编写需要清理的东西才能退出该功能.

例如,我创建了一个文件,并映射了一个文件的视图.

通常,我只是使用gotodo {break;} while(false);退出.但是,C++ 11不再需要它吗?

不过了

if( fail ) {
        UnmapViewOfFile(lpMapView);
        CloseHandle(hFileMap);
        CloseHandle(hFile);
}
Run Code Online (Sandbox Code Playgroud)

每几行代码?

一旦函数退出,编译器是否会自动将其包装起来?它似乎很难相信它实际上清理了文章所说的功能调用.(我可能会以某种方式误解它.)更可能的是,它只是通过从C++库调用它们的解构函数来清理创建的类库.

编辑:文章 - 来自维基百科:

这不一定表明它清理这些函数调用,但它确实意味着它为C++库函数的对象(如FILE *,fopen等对象)

它也适用于WinAPI吗?

mar*_*inj 7

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)

  • 您并不总是需要为句柄编写自己的句柄,"unique_ptr"和"shared_ptr"都支持自定义删除. (5认同)

Che*_*Alf 7

清理仍然是必要的,但由于可能存在异常,代码不应仅通过在函数结束时执行清理操作来进行清理.可能永远无法达到这一目的!代替,

    在析构函数中进行清理.

在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_ptrunique_ptr,从而照顾指针的所有权,调用删除器时,业主人数变为0顾名思义,他们分别实现共享和独特的所有权.它们都可以将自定义删除器作为参数,但仅shared_ptr支持在将智能指针复制/移动到基类指针时使用原始指针值调用自定义删除器.

另外,我还应该更好地提到标准库容器类,特别是vector提供动态大小的可复制数组,具有自动内存管理,并且对于表示字符串string的特定用例数组提供了大致相同的功能char.这些类释放你不必直接处理newdelete,并获得这些细节的权利.

总而言之,

  • 使用标准库和/或3 时即可党的容器,

  • 否则使用标准库和/或3 聚会智能指针,

  • 如果即使这样做并不能满足你的清理需求,也可以定义在析构函数中进行清理的自定义类.