将值传递给atexit

时间:2011-11-08 15:39:28

标签: c++ boost-bind atexit

我想在需要时推出一系列清理功能。我使用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

提前致谢!

3 个答案:

答案 0 :(得分:3)

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 );
}

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

答案 1 :(得分:2)

没有“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 f\n");

    static AtExitAnimationCloser s0 ("0"); // registers closeAnimation("0") at exit
    static AtExitAnimationCloser s1 ("1"); // registers closeAnimation("0") at exit

    printf("leaving f\n");
}

示范: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的向量,它在destroy~T调用fileWriter::closeAnimation上。

答案 2 :(得分:-1)

问题是bind返回一个函数对象,atexit接受一个指向函数的指针,该函数返回void并且没有参数。

你可以试试这个:

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

atexit(fun);