Functions are usually in an area called static.
The space occupied by the binary code of the functions is there regardless of whether there is an instance or not, because the instantiation has nothing to do with the codes. Basically functions are more independent than people realize.
Just as functions only take up space once, and not for each instance created. The function (your code) is global. If you think of the code as a given, there’s no reason for more than one copy of it. Even if it runs several times in different situations, the code itself only needs to exist once.
If you change the code (if you can do this) will be changed to all instances, after all there is only one function for all.
It is important to note that the space occupied in memory is relative. It may not occupy anything in RAM memory. The code is usually loaded by file mapping in memory and the operating system effectively loads into memory only the pages being used. So a never-called function has a good chance of never entering RAM memory. It will, of course, occupy a space in virtual addressing, but that is already another matter.
Of course, if there are no instances of a class, there is a possibility, by optimization, of the compiler/linkeditor not include any code in the application executable.
But even other codes that never came close to your code can be included together by being together with codes that your code effectively used. Codes are in inseparable compilation units. If you use a function of a compilation unit, everything in that unit will go. It is common that the unit has only the specific class or others that have total dependence on it (already optimizations that are more granular, but this is not so common yet).
It is good to understand that there are no actual instance functions. Everything is normal function. What differentiates being from instance is the function having a first parameter (usually hidden) called this
which is a pointer to the instance itself. I will also not go into detail here, it is not the focus.
The exact way this will all proceed may vary in each compiler implementation and may be better adapted to each operating system. But none that I know invented something very innovative.
Consider that it is possible to have an application that allows code injection at runtime, which allows Just-in-Time compilation, or other juggling that slightly modifies this idea (not much), but none of these tricks are common in C++.
Remember that these areas of spoken memory are abstract concepts. There is nothing that physically demarque each part. In the background the static area is not very different from the others. In general it is a little more protected by the operating system against changes, as indicated by the Runtime of language.
There are occupied spaces that many do not see. There are overhead in object allocation, in addition to its own size, there is data of saved types, there are virtual tables for dynamic polymorphism, etc. Again everything depends on implementation.
The programmer doesn’t have to manage that memory, she has lifespan throughout the application.
Obviously several of these details can be more scrutinized in other questions.
Note that any response will be specific to certain compilers and not to C++ as a whole. The C++ standard does not require, for example, cell separation and heap.
– Pablo Almeida