C++ 学习笔记 (8) 初识 atexit 函数

atexit 函数

称为终止处理程序注册程序,注册完成以后,当函数终止是exit()函数, 会主动的调用前面注册的各个函数

特点

  1. 调用 exit 函数时,会主动调用被注册的函数,执行清理工作
  2. 发生在 main 函数结束之后
  3. 函数参数是函数的地址
  4. 先注册的函数后实现,类似于栈
  5. 只接受无返回类型,即 void 类型的函数

简单测试:

#include <bits/stdc++.h>
#define rep( i , j , n ) for ( int i = int(j) ; i < int(n) ; ++i )
#define dew( i , j , n ) for ( int i = int(n-1) ; i > int(j) ; --i )
#define display( say )  std::cout << std::endl << say << std::endl 
#define _PATH __FILE__ , __LINE__
typedef std::pair < int , int > P ;
using std::cin ;
using std::cout ;
using std::endl ;
using std::string ;

class Gragh {
private:
    int data ;
public:
    Gragh () : data ( 0 ) {
        const char* say = "我是默认构造函数" ;
        display ( say ) ;
        atexit ( My_test ) ;
    }
    explicit Gragh ( int _data ) : data ( _data ) {
        const char* say = "我是构造函数" ;
        display ( say ) ;
    }
    // error: cannot convert 'Gragh::My_test' from type 'void (Gragh::)()' to type 'void (*)()' 
    static void My_test () {
        const char* say = "我是类的 static void 函数" ;
        display ( say ) ;
    }
    void test_void () {
        const char* say = "我是 void 的普通成员函数" ;
        display ( say ) ;
    }
    ~Gragh () {
        const char* say = "我是析构函数" ;
        display ( say ) ;
    }
} ;

void test1 () {
    const char* say = "I am test1" ;
    display ( say ) ;
}

void test2 () {
    const char* say = "I am test2" ;
    display ( say ) ;
}

void test3 () {
    const char* say = "I am test3" ;
    display ( say ) ;
}

void test4 () {
    const char* say = "I am test4" ;
    display ( say ) ;
    Gragh *One = nullptr ;
    One->test_void () ;
}

bool test5 () {
    const char* say = "I am test5" ;
    display ( say ) ;
    return true ;
}

int main () {
    atexit ( test1 ) ;
    atexit ( test2 ) ;
    atexit ( test3 ) ;
    Gragh *One = new Gragh () ;
    delete One ;
    atexit ( test4 ) ;  // 在 main 函数之后调用
    atexit ( Gragh::My_test ) ;
    // atexit ( test5 ) ;
    // error: invalid conversion from 'bool (*)()' to 'void (*)()' [-fpermissive]
    const char* say = "我是 main 函数" ;
    display ( say ) ;
    return 0 ;
}

程序运行结果:

这里写图片描述

笔记

  1. 被注册的函数类似于入栈,先进后出。这为程序员提供了一种自主决定函数调用先后关系的手段
  2. 被注册的最后一个函数是 static void 函数,所以,最早调用,一般在面对对象中可以采用这种方式释放内存,或者容器清空的操作
  3. 支持普通 void 函数
    支持对象中的 void 函数
    支持类中的 static void 函数。
    原因可能是, atexit 函数是在 main 函数结束之后会被 exit 触发,而 static 关键字是全局的,可见全局变量区和类,对象的的函数的生存期都比 main 的生存期更长
  4. 在 main 函数结束之后,还可以输出语句,说明了 I/O 流的清理工作晚于 main 函数,而且晚于 atexit 函数

猜你喜欢

转载自blog.csdn.net/nishisiyuetian/article/details/80272333
今日推荐