Hello, can someone tell me how I can use the atexit() function with class members?

Dani AI

Generated

For : a non‑static member function cannot be passed directly to std::atexit because atexit requires a plain void(*)() function pointer (a member function needs a this pointer). As suggested, prefer RAII/destructors for cleanup. When atexit is necessary, register a static (or free) function that forwards to an instance.

Example pattern — register a static forwarder that calls the stored instance:

#include <cstdlib>

class Cleaner {
public:
    Cleaner() { s_instance = this; std::atexit(&Cleaner::atexit_handler); }
    ~Cleaner() { /* normal destructor */ }
    void cleanup() noexcept {
        // minimal, safe cleanup here
    }
private:
    static void atexit_handler() noexcept {
        if (s_instance) s_instance->cleanup();
    }
    static Cleaner* s_instance;
};

Cleaner* Cleaner::s_instance = nullptr;

// provide one instance with static storage:
static Cleaner global_cleaner;

Notes and cautions: keep atexit handlers tiny and noexcept; avoid depending on other static objects (initialization/destruction order can be tricky); capturing lambdas cannot be used, but a captureless lambda can convert to a plain function pointer in C++11+ if desired. If multiple instance-specific handlers are needed, register one small C-level wrapper that iterates a carefully managed list of callables — but be cautious about dynamic allocation and initialization order. Prefer deterministic RAII/destructors over atexit when possible.

a. place the call to the exit handler member function in the destructor of a class.
b. create an instance of the class with a static storage duration.

the order of calling C atexit / C++ destructors for objects with a static storage duration is specified by secion 3.6.3/3 of the standard:

If a function is registered with atexit then following the call to exit, any objects with static storage duration initialized prior to the registration of that function shall not be destroyed until the registered function is called from the termination process and has completed.
For an object with static storage duration constructed after a function is registered with atexit, then following the call to to exit, the registered function is not called until the execution of the object's destructor has completed.
If atexit is called during the construction of an object, the complete object to which it belongs shall be destroyed before the registered function is called.

for example, for the following program:

#include <iostream>
#include <cstdlib>

struct clean_up
{
  explicit clean_up( const char* m ) : msg(m) {}
  void do_clean_up()
  { std::cout << msg << ": cleaning up via mem fun...\n" ; }
  ~clean_up() { do_clean_up() ; }
  const char* const msg ;
};

void at_exit_one()
{ std::cout << "one: cleaning up via free fun...\n" ; }

void at_exit_three()
{ std::cout << "three: cleaning up via free fun...\n" ; }

int main()
{
  std::atexit( at_exit_one ) ;
  static clean_up two( "two" ) ;
  std::atexit( at_exit_three ) ;
  static clean_up four( "four" ) ;
}

the output would be:

four: cleaning up via mem fun...
three: cleaning up via free fun...
two: cleaning up via mem fun...
one: cleaning up via free fun...
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.