当前位置:编程学习 > C/C++ >>

利用已有的bind构造ScopeExit

对于 ScopeExit,以前有提到过(见《这种代码结构如何组织?goto or do…while(0)?》http://www.zzzyk.com/kf/201205/132632.html)。使用场景再简单提一下:
bool GenFile()
{
    HANDLE hFile = CreateFile(_T("Test.txt"), GENERIC_WRITE, 0, NUL, CREATE_ALWAYS, 0, NULL);
 
    if (hFile == INVALID_HANDLE_VALUE)
    {
        return false;
    }
 
    CString strData = _T("test");
    DWORD dwToWrite = strData.GetLength() * sizeof(TCHAR);
    DWORD dwWritten = 0;
 
    if (!WriteFile(hFile, (LPCTSTR)strData, dwToWrite, &dwWritten, NULL) || dwWritten != dwToWrite)
    {
        CloseHandle(hFile);
        return false;
    }
 
//     if (...)
//     {
//         CloseHandle(hFile);
//         return false;
//     }
//
//     ...
//
 
    CloseHandle(hFile);
 
    return true;
}
 
如上面这部分代码,如果 if … 之类的流程持续下去(如注释部分),每个 return false 之前都得带上 CloseHandle(),非常累赘。因此,出现了类似的 ScopeExit。boost 里有一个 BOOST_SCOPE_EXIT,Loki 里面也有一个 ScopeGuard。
继续使用刚才的案例,BOOST_SCOPE_EXIT 用法:
bool GenFile()
{
    HANDLE hFile = CreateFile(_T("Test.txt"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
 
    if (hFile == INVALID_HANDLE_VALUE)
    {
        return false;
    }
 
    BOOST_SCOPE_EXIT((hFile))
    {
        CloseHandle(hFile);
    }
    BOOST_SCOPE_EXIT_END
 
    CString strData = _T("test");
    DWORD dwToWrite = strData.GetLength() * sizeof(TCHAR);
    DWORD dwWritten = 0;
 
    if (!WriteFile(hFile, (LPCTSTR)strData, dwToWrite, &dwWritten, NULL) || dwWritten != dwToWrite)
    {
        return false;
    }
 
//     if (...)
//     {
//         return false;
//     }
//
//     ...
//
 
    return true;
}
 
这样,每个 return 之前再也不必背负 CloseHandle 的包袱。
Loki::ScopeGuard 的用法:
bool GenFile()
{
    HANDLE hFile = CreateFile(_T("Test.txt"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
 
    if (hFile == INVALID_HANDLE_VALUE)
    {
        return false;
    }
 
    LOKI_ON_BLOCK_EXIT(CloseHandle, hFile);
 
    CString strData = _T("test");
    DWORD dwToWrite = strData.GetLength() * sizeof(TCHAR);
    DWORD dwWritten = 0;
 
    if (!WriteFile(hFile, (LPCTSTR)strData, dwToWrite, &dwWritten, NULL) || dwWritten != dwToWrite)
    {
        return false;
    }
 
//     if (...)
//     {
//         return false;
//     }
//
//     ...
//
 
    return true;
}
 
从使用的简洁程度上看,Loki 更胜一筹。
另外,我们经常也遇到有条件的执行清理动作的情形,boost 和 Loki 都支持。先看 Loki 的使用案例:
bool GenFile()
{
    LPCTSTR FILE_NAME = _T("Test.txt");
    HANDLE hFile = CreateFile(FILE_NAME, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
 
    if (hFile == INVALID_HANDLE_VALUE)
    {
        return false;
    }
 
    Loki::ScopeGuard sgDeleteFile = Loki::MakeGuard(DeleteFile, FILE_NAME);
    LOKI_ON_BLOCK_EXIT(CloseHandle, hFile);
 
    CString strData = _T("test");
    DWORD dwToWrite = strData.GetLength() * sizeof(TCHAR);
    DWORD dwWritten = 0;
 
    if (!WriteFile(hFile, (LPCTSTR)strData, dwToWrite, &dwWritten, NULL) || dwWritten != dwToWrite)
    {
        return false;
    }
 
//     if (...)
//     {
//         return false;
//     }
//
//     ...
//
 
    sgDeleteFile.Dismiss();
 
    return true;
}
 
一开始,我们使用具名的 ScopeGuard,绑定了一个 DeleteFile(FILE_NAME) 的操作,到最后通过 Dismiss,让此操作不被执行。
相应地,boost 中,可以在进入 scope exit 之前设定一个变量,将此变量捕获入 scope exit,到最后给这个变量赋值,决定执不执行:
bool GenFile()
{
    LPCTSTR FILE_NAME = _T("Test.txt");
    HANDLE hFile = CreateFile(FILE_NAME, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
 
    if (hFile == INVALID_HANDLE_VALUE)
    {
        return false;
    }
 
    bool bOK = false;
 
    BOOST_SCOPE_EXIT((hFile)(&bOK))
    {
        if (!bOK)
        {
            CloseHandle(hFile);
        }
    }
    BOOST_SCOPE_EXIT_END
 
    CString strData = _T("test");
    DWORD dwToWrite = strData.GetLength() * sizeof(TCHAR);
    DWORD dwWritten = 0;
 
    if (!WriteFile(hFile, (LPCTSTR)strData, dwToWrite, &dwWritten, NULL) || dwWritten != dwToWrite)
    {
        return false;
    }
 
//     if (...)
//     {
//         return false;
//     }
//
//     ...
//
 
    bOK = true;
 
    return true;
}
注意,此处捕获 bOK 的时候才用指针的形式,以保证最后对

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,