Look at the following code in two files:
-
main.cpp
#include <iostream> extern const char *text; int main() { std::cout << text << std::endl; return 0; }
-
lib.cpp
#include <iostream> namespace { class SomeClass { public: SomeClass(const char *text) { std::cout << text << std::endl; } }; } SomeClass anInstance("Hello, world."); const char *text = "Bye, world.";
g++ lib.cpp main.cpp && ./a.out
This yields
Hello, world.
Bye, world.
g++ -c lib.cpp -o lib.o && ar r libfoo.a lib.o && g++ main.cpp -L. -lfoo && ./a.out
This also yields
Hello, world.
Bye, world.
Now we modify main.cpp:
#include <iostream>
//extern const char *text;
int main()
{
//std::cout << text << std::endl;
return 0;
}
Notice how we removed any reference to symbols from lib.cpp.
With an unmodified command line, this now yields
Hello, world.
Notice how the initializer of anInstance is still run.
Here is where it gets interesting: The binary doesn't print anything.
While usually linking all object files that are given to it, the linker seems to completely discard object files from static libraries if no symbols are referenced from the outside, even if globals are concerned.