C++ Boost ScopeExit超详细讲解

 更新时间:2022年11月17日 10:37:36   作者:无水先生  
最近研究了boost中的ScopeExit,发现是个这是个很高级的特性,可以在作用域结束时自动关闭已经打开的资源或做某些清理操作,这篇文章主要介绍了C++ Boost ScopeExit

一、提要

资源有很多种,每种都封装一套,还是挺繁琐的!对于比较少使用或者一个程序很可能只会用一次的资源,我们不想封装,在这种情况下用Boost.ScopeExit。

二、退出作用域(Boost.ScopeExit)

库 Boost.ScopeExit 使得在没有资源特定类的情况下使用 RAII 成为可能。

2.1 范例1.UsingBOOST_SCOPE_EXIT

#include <boost/scope_exit.hpp>
#include <iostream>
int *foo()
{
  int *i = new int{10};
  BOOST_SCOPE_EXIT(&i)
  {
    delete i;
    i = 0;
  } BOOST_SCOPE_EXIT_END
  std::cout << *i << '\n';
  return i;
}
int main()
{
  int *j = foo();
  std::cout << j << '\n';
}

计算结果:

Boost.ScopeExit 提供了宏 BOOST_SCOPE_EXIT,它可以用来定义一些看起来像本地函数但没有名字的东西。但是,它确实有一个括号中的参数列表和大括号中的块。 必须包含头文件 boost/scoped_exit.hpp 才能使用 BOOST_SCOPE_EXIT。

宏的参数列表包含来自外部范围的变量,这些变量应该可以在块中访问。变量通过副本传递。要通过引用传递变量,它必须以 & 符号作为前缀,如示例2.1 范例1. 中所示。

如果变量在参数列表中,则块中的代码只能从外部范围访问变量。

BOOST_SCOPE_EXIT 用于定义一个块,该块将在定义块的范围结束时执行。在示例 3.1 中,使用 BOOST_SCOPE_EXIT 定义的块在 foo() 返回之前执行。

BOOST_SCOPE_EXIT 可用于从 RAII 中受益,而无需使用特定于资源的类。 foo() 使用 new 创建一个 int 变量。为了释放变量,使用 BOOST_SCOPE_EXIT 定义了一个调用 delete 的块。即使函数由于异常而提前返回,也保证执行此块。在示例 1 中,BOOST_SCOPE_EXIT 与智能指针一样好。

请注意,变量 i 在 BOOST_SCOPE_EXIT 定义的块末尾设置为 0。然后 i 由 foo() 返回并写入 main() 中的标准输出流。但是,该示例不显示 0。j 设置为随机值 - 即 int 变量在内存被释放之前所在的地址。 BOOST_SCOPE_EXIT 后面的块获得了对 i 的引用并释放了内存。但由于该块是在 foo() 的末尾执行的,因此将 0 分配给 i 为时已晚。 foo() 的返回值是在 i 设置为 0 之前创建的 i 的副本。

如果您使用 C++11 开发环境,则可以忽略 Boost.ScopeExit。在这种情况下,您可以在 lambda 函数的帮助下使用没有资源特定类的 RAII。

2.2 示例2.Boost.ScopeExit和C++11的lambda函数

#include <iostream>
#include <utility>
template <typename T>
struct scope_exit
{
  scope_exit(T &&t) : t_{std::move(t)} {}
  ~scope_exit() { t_(); }
  T t_;
};
template <typename T>
scope_exit<T> make_scope_exit(T &&t) { return scope_exit<T>{
  std::move(t)}; }
int *foo()
{
  int *i = new int{10};
  auto cleanup = make_scope_exit([&i]() mutable { delete i; i = 0; });
  std::cout << *i << '\n';
  return i;
}
int main()
{
  int *j = foo();
  std::cout << j << '\n';
}

运算结果:

示例2 定义了类 scope_exit,其构造函数接受一个函数。该函数由析构函数调用。此外,还定义了一个辅助函数 make_scope_exit(),它可以在无需指定模板参数的情况下实例化 scope_exit。

在 foo() 中,一个 lambda 函数被传递给 make_scope_exit()。 lambda 函数看起来像示例 3.1 中 BOOST_SCOPE_EXIT 之后的块:地址存储在 i 中的动态分配的 int 变量通过删除被释放。然后将 0 分配给 i。

该示例与前一个示例执行相同的操作。不仅 int 变量被删除,而且 j 在写入标准输出流时也没有设置为 0。

2.3 示例3.特点BOOST_SCOPE_EXIT

#include <boost/scope_exit.hpp>
#include <iostream>
struct x
{
  int i;
  void foo()
  {
    i = 10;
    BOOST_SCOPE_EXIT(void)
    {
      std::cout << "last\n";
    } BOOST_SCOPE_EXIT_END
    BOOST_SCOPE_EXIT(this_)
    {
      this_->i = 20;
      std::cout << "first\n";
    } BOOST_SCOPE_EXIT_END
  }
};
int main()
{
  x obj;
  obj.foo();
  std::cout << obj.i << '\n';
}

示例介绍了 BOOST_SCOPE_EXIT 的一些特性:

  • 当 BOOST_SCOPE_EXIT 用于在一个范围内定义多个块时,这些块以相反的顺序执行。示例 3 先显示后显示。
  • 如果没有变量将传递给 BOOST_SCOPE_EXIT,则需要指定 void。括号不能为空。
  • 如果您在成员函数中使用 BOOST_SCOPE_EXIT 并且需要传递指向当前对象的指针,则必须使用 this_ 而不是 this。

示例3:显示first,last, 和20in that order.

三、练习

BOOST_SCOPE_EXIT(&flag) {
} BOOST_SCOPE_EXIT_END

BOOST_SCOPE_EXIT和 BOOST_SCOPE_EXIT_END都是配合着使用的, BOOST_SCOPE_EXIT()里面可以传入多个参数。其作用相当于回调函数,

在作用域结束之后程序会自动调用 BOOST_SCOPE_EXIT到 BOOST_SCOPE_EXIT_END之间的代码。

包含的头文件是 #include <boost/scope_exit.hpp>

下面是一个简单的例子:

#include  <boost/scope_exit.hpp>
void PrintCout(const std::string& str)
{
    bool submitted = false;
    BOOST_SCOPE_EXIT(&submitted ) {
        if (!submitted)
            std::cout<<"false"<<std::endl;
        else
            std::cout<<"true"<<std::endl;
    } BOOST_SCOPE_EXIT_END
    submitted = ((str == "Y")? true:false);
}
int main(int argc, char* argv[])
{
    std::string str;
    std::cin>>str;
    while(str != "q"){
        PrintCout(str);
        std::cin>>str;
    }
}

这里的 BOOST_SCOPE_EXIT()可以传入多个参数,格式:

BOOST_SCOPE_EXIT(&parameter1,&parameter2,...)

到此这篇关于C++ Boost ScopeExit超详细讲解的文章就介绍到这了,更多相关C++ Boost ScopeExit内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++实现LeetCode(79.词语搜索)

    C++实现LeetCode(79.词语搜索)

    这篇文章主要介绍了C++实现LeetCode(79.词语搜索),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C++存储方案和动态分配

    C++存储方案和动态分配

    这篇文章主要介绍了C++存储方案和动态分配,
    2021-12-12
  • 基于C++类型重定义的使用详解

    基于C++类型重定义的使用详解

    本篇文章是对C++中类型重定义的使用进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • c语言实现把文件中数据读取并存到数组中

    c语言实现把文件中数据读取并存到数组中

    下面小编就为大家带来一篇c语言实现把文件中数据读取并存到数组中。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12
  • 一篇文章带你了解C++(STL基础、Vector)

    一篇文章带你了解C++(STL基础、Vector)

    这篇文章主要为大家详细介绍了C++ STL基础,vector向量容器使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能给你带来帮助
    2021-08-08
  • 用C语言实现简单的计算器功能

    用C语言实现简单的计算器功能

    这篇文章主要为大家详细介绍了用C语言实现简单的计算器功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • c++ decltype关键字的用法

    c++ decltype关键字的用法

    这篇文章主要介绍了c++ decltype关键字的用法,帮助大家更好的理解和学习c++,感兴趣的朋友可以了解下
    2020-10-10
  • C语言中的各种文件读写方法小结

    C语言中的各种文件读写方法小结

    这篇文章主要介绍了C语言中的各种文件读写方法小结,是C语言入门学习中的基础知识,需要的朋友可以参考下
    2015-07-07
  • Qt中QDateTimeEdit的具体使用

    Qt中QDateTimeEdit的具体使用

    本文主要介绍了Qt中QDateTimeEdit的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-06-06
  • 详细分析C++ 信号处理

    详细分析C++ 信号处理

    这篇文章主要介绍了C++ 信号处理的相关资料,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07

最新评论