首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将值传递给atexit

将值传递给atexit
EN

Stack Overflow用户
提问于 2011-11-08 23:39:28
回答 3查看 4.3K关注 0票数 4

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

在c++中,我正在尝试让以下内容正常工作:

函数定义

代码语言:javascript
复制
static void closeAnimation(string prefix="");// static member of fileWriter

代码:

代码语言:javascript
复制
atexit(boost::bind(fileWriter::closeAnimation, "0")); // I want to first prefix to be "0"

错误:

代码语言:javascript
复制
cannot convert ‘boost::_bi::bind_t<void, void (*)(std::basic_string<char>), boost::_bi::list1<boost::_bi::value<const char*> > >’ to ‘void (*)()’ for argument

提前感谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-11-08 23:56:09

没有“不使代码复杂化的单行解决方案”。

最糟糕的解决方案是将参数存储在全局变量中,然后在atexit处理程序中检索它

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

代码语言:javascript
复制
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

请注意,静态变量被绑定到它们的名称,因此您不能使用

代码语言:javascript
复制
for (it = vecs.begin(); it != vecs.end(); ++ it)
{
   static AtExitAnimationCloser s (*it);
}

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

代码语言:javascript
复制
static AnotherAtExitAnimationCloser s (vecs.begin(), vecs.end())

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

票数 3
EN

Stack Overflow用户

发布于 2011-11-09 00:29:38

atexit是一个遗留的C函数,不太适合C++。您可以使用atexit注册多个函数,但所有函数都必须为void (*)(),没有boost::function,也没有参数。

在C++中,atexit的大部分功能(如果不是全部的话)都包含在静态对象的析构函数中。

代码语言:javascript
复制
#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派生的类,只要您采取措施确保所有实例都是动态分配的(因为构造函数会注册对象以便将其删除);这些类可以包含您想要的任何附加数据。

票数 3
EN

Stack Overflow用户

发布于 2011-11-08 23:45:27

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

您可以尝试这样做:

代码语言:javascript
复制
void fun() {
    fileWriter::closeAnimation("0");
}

atexit(fun);
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8053000

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档