将值传递给atexit

Passing values to atexit

本文关键字:atexit 值传      更新时间:2023-10-16

我想在需要时推送一系列清理函数。我使用atexit对一个没有任何参数的清理函数执行此操作,但我不确定如何将这种方法扩展到多个清理函数。我不是很熟悉boost::bind,但假设这将是一个好主意,因为这就是我如何将函数绑定到线程…

在c++中,我试图得到以下工作:

函数定义

static void closeAnimation(string prefix="");// static member of fileWriter
代码:

atexit(boost::bind(fileWriter::closeAnimation, "0")); // I want to first prefix to be "0"

错误:

cannot convert ‘boost::_bi::bind_t<void, void (*)(std::basic_string<char>), boost::_bi::list1<boost::_bi::value<const char*> > >’ to ‘void (*)()’ for argument

提前感谢!

如果不使代码复杂化,就没有" 1行"的解决方案。

最糟糕的解决方案是将该参数存储在全局变量中,并在atexit处理程序

中检索它。

由于使用的是c++,静态变量的析构函数也可以用作atexit处理程序。然后你可以在静态变量的构造函数中传递参数进行参数化,例如

struct AtExitAnimationCloser
{
    const char* _which_param;
    AtExitAnimationCloser(const char* which_param) : _which_param(which_param) {}
    ~AtExitAnimationCloser() { FileWriter::closeAnimation(_which_param); }
};
void f()
{
    printf("entering fn");
    static AtExitAnimationCloser s0 ("0"); // registers closeAnimation("0") at exit
    static AtExitAnimationCloser s1 ("1"); // registers closeAnimation("1") at exit
    printf("leaving fn");
}

示范:http://www.ideone.com/bfYnY

注意,静态变量绑定到它们的名称,所以不能说
for (it = vecs.begin(); it != vecs.end(); ++ it)
{
   static AtExitAnimationCloser s (*it);
}

对所有内容调用atexit。但是你可以让静态变量本身取整个范围

static AnotherAtExitAnimationCloser s (vecs.begin(), vecs.end())

最后,对于习惯的c++,我认为你不需要使用这些技巧…您可以存储类型为T的向量,在销毁~T时调用fileWriter::closeAnimation

atexit是一个遗留的C函数,不太适合c++。你可以在atexit中注册多个函数,但所有函数都必须注册void (*)(),无boost::function,无参数

在c++中,atexit的大部分功能(如果不是全部的话)都被包含进去了静态对象的析构函数。如果是你,我会写点什么如:

#include <vector>
class CallInDestructor
{
    class Registry
    {
        std::vector<CallInDestructor*> myInstances;
    public:
        register_caller(CallInDestructor* caller)
        {
            myInstances.push_back(caller);
        }
        ~Registry()
        {
            while ( !myInstances.empty() ) {
                delete myInstances.back();
                myInstances.pop_back();
            }
        }
    };
    static Registry& registry()
    {
        static Registry theOneAndOnly;
        return theOneAndOnly;
    }
protected:
    CallInDestructor() { registry().register_caller( this ); }
public:
    virtual ~CallInDestructor() {}
};
template<typename Fnc> void callAtExit( Fnc fnc );
template<typename Fnc>
class ConcreteCallInDestructor : public CallInDestructor
{
    Fnc myFnc;
    ConcreteCallInDestructor( Fnc fnc = Fnc() ) : myFnc( fnc ) {}
    virtual ~ConcreteCallInDestructor() { myFnc(); }
    friend void callAtExit<Fnc>( Fnc fnc );
};
template<typename Fnc>
void
callAtExit( Fnc fnc )
{
    new ConcreteCallInDestructor<Fnc>( fnc );
}

像使用atexit一样使用callAtExit,但它应该适用于任何情况它可以不带参数调用(包括boost::function)。或者您可以编写自己的类,从CallInDestructor派生,如只要采取措施确保所有实例都是动态的已分配(因为构造函数注册了对象,所以它将被分配)删除);这些类可以包含您想要的任何其他数据。

问题是bind返回一个函数对象,而atexit接受一个指向一个返回void且不带形参的函数的指针。

你可以试试:

void fun() {
    fileWriter::closeAnimation("0");
}
atexit(fun);