ARTICLE AD BOX
This question is about the singleton pattern in modern C++ and one of its limitations in particular.
I can implement the singleton pattern like this:
class Logger { public: static Logger& instance() { static Logger singleton {}; return singleton; } Logger(const Logger&) = delete; auto operator= (const Logger&) = delete; // ... member functions declared here };Now, consider some client code using the singleton:
void start() { auto& logger = Logger::instance(); logger.debug("start() called"); // ... }My issue with this is: although singletons have only one instance, every member function call will require the compiler to pass the this pointer along with the arguments. This is wasteful. I could imagine that a procedural implementation of the logger, written in C, would outperform this singleton implementation.
For the same reason, C++23 allowed for operator () and [] to be declared static. Which avoids having to pass a this pointer with each call.
Theoretically, the compiler could optimize away the implicit this pointer argument, because its location is known at compile-time (the address of the local static variable). But I guess the compiler does not know.
Maybe this is more a discussion about language features than asking for an actual solution.
Update:
To make my case clearer, I have prepared an example in Compiler explorer. Comparing the singleton function call with that of the free function in the assembly:
Singleton:
mov esi, OFFSET FLAT:.LC0 mov rdi, rax call Logger::log_debug(const char*)Free function:
mov edi, OFFSET FLAT:.LC0 call log_debug(const char*)See what I mean? The free function call needs two instructions (in x86_64), whereas the singleton call needs three. The value returned by get_instance() will never change. Still, it is passed with every function call. This is what I meant by wasteful above.
