如何用atexit()注册一个非void函数?

How to register a non-void function with atexit()?

我正在尝试注册一个函数,该函数 return 是一个 int,将在使用 atexit() 函数的程序结束时调用。 (具体来说,来自 ncurses 的 endwin() 函数。)

但是由于atexit()需要一个指向void函数的指针,我运行遇到了问题。我尝试了以下方法:

static_cast<void (*)()>(endwin)

但是 static_castint 函数到 void 函数似乎是不允许的。

我正在努力实现的目标是否可行?如果可行,如何实现?

注意:我愿意忽略函数的return值。


编辑:我还尝试创建一个 lambda 函数,它似乎可以满足我的要求:

atexit([]{ endwin(); });

与 wrapper/forwarding 函数相比,这是一个好的解决方案吗? (除此之外,它需要 C++11 并避免定义一个新函数,其唯一目的只是转发另一个函数。)

"Is what I'm trying to accomplish possible at all, and if yes, how?"

您只需为 endwin() 编写自己的包装函数并注册那个

void myEndwin() {
    endwin();
}

无法转换函数指针。只需注册一个转发功能:

#ifdef __cplusplus
extern "C"
#endif
void endwin_wrapper() { endwin(); }
...
atexit(endwin_wrapper);

由于您将问题标记为 C++:如果您在 C++ 中定义转发函数,则需要将其声明为 extern "C" 以获得正确的语言链接。

根据当前的 C++ 标准,lambda 可能是解决此问题的最佳方法:

atexit([]{ endwin(); });

现在没有必要为了转发另一个函数而定义一个全新的命名函数。


如果有一天您决定需要在程序退出时调用更多函数,您可以通过对 atexit():

的新调用来定义它们
atexit(anotherCleanupFunction);

或者,您可以将它们添加到 lambda 主体中:

atexit([]{
  anotherCleanupFunction();
  endwin();
});

但是,当您有多个函数要在 atexit() 中注册时,一个单独的包装函数来保存所有这些函数可能是更好的解决方案。虽然没有唯一的正确答案,只需编写良好且清晰的代码即可。 (通过充满函数调用的 lambda 调用 atexit() 可能看起来相当混乱。)