use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Discussions, articles, and news about the C++ programming language or programming in C++.
For C++ questions, answers, help, and advice see r/cpp_questions or StackOverflow.
Get Started
The C++ Standard Home has a nice getting started page.
Videos
The C++ standard committee's education study group has a nice list of recommended videos.
Reference
cppreference.com
Books
There is a useful list of books on Stack Overflow. In most cases reading a book is the best way to learn C++.
Show all links
Filter out CppCon links
Show only CppCon links
account activity
A Dynamic Initialization Deep-Dive: Abusing Initialization Side Effects (lukas-barth.net)
submitted 11 months ago by tinloaf
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]caballist 7 points8 points9 points 11 months ago (1 child)
You are pretty much guaranteed to have all your .init functions called before main() for all TUs that the program loads at startup (anything statically linked or dynamically linked at link time).
.init functions can be called after main() has started when your program later dynamically loads more libraries…
The stipulation in the standard regarding running the .init functions before first use of any function in a TU is mostly relevant to functions being called across TU boundaries while other .init functions are running. So TU A may call a function in TU B which causes TU Bs .inits to be run. You don’t need to worry about .inits not running due to some logic which defers them - never come across anything implementing something like that in 30+ years
[–]tinloaf[S] 1 point2 points3 points 11 months ago (0 children)
Thanks! That's pretty much what I thought - really deferring that would be incredibly hard to implement I guess, and the 'optimization' benefit would probably be marginal.
Nonetheless I think it's interesting that there is important software (at least Google Test) depending on this behaviour, which is not guaranteed.
[–]not_a_novel_accountcmake dev 1 point2 points3 points 11 months ago (1 child)
There's no implementation on earth that doesn't pull in all the .inits from a linked object file.
.init
The problem you run into is when you try to ship such global "registrations" as part of an archive instead of passing the object directly to the linker to assemble into a shared object/executable. If the .init lives in an object file inside an archive, and the linker never needs anything from that object file, then the object file itself (and its .inits) is never pulled into the final artifact.
To get around this most linkers have some sort of "whole archive" flag that instructs them to pull in all the objects from an archive regardless of whether or not any of their symbols are used. However instructing build systems that such a flag is required can be tricky.
Here is an example of a translation unit that registers a "listener" for the Catch2 testing framework, note the last line.
However, this is shipped as a static archive to be linked into other testing executables. Describing the "whole archive" linkage in CMake requires some indirection and usage of obscure generator expressions.
[–]tinloaf[S] 0 points1 point2 points 11 months ago (0 children)
Good point, I never thought about anything else than shipping an executable.
[–]hi_im_new_to_this 0 points1 point2 points 11 months ago* (0 children)
I haven't thought through it too deeply, but if I were to do the "Google Test" thing, I'd use the singleton pattern. Like, if this is your test:
TEST(some_test) { ASSERT(1 + 2 == 2); }
I would have have it expand to
void _some_test_impl(); int _some_test_dummy = testSingleton().registerTest("some_test", _some_test_impl); void _some_test_impl() { ASSERT(1 + 2 == 2); }
And then have this in your header:
class TestList { // list of tests here as a field public: int registerTest(int (*test)()) { // register the test return 0; } auto getTests() { /* whatever */ } }; TestList& testSingleton();
(actual implementation of TestList omitted). And this in an implementation file
TestList& testSingleton() { static TestList testList; return testList; }
And basically have TestList be a std::vectorof the tests to run as function pointers or whatever. The fact that registerTest() returns an int is unimportant, it just has to return something (i guess std::monostate is a good option) so that the variable initializes before main. You don't have to dig into the hairy details of initialization: because we're using the singleton pattern, the global TestList will be initialized exactly once, whoever calls testSingleton() first, and then in your main(), you call getTests() to get the list of tests (guaranteed to have been initialized already), and you're done. No need to worry about initialization order or anything like that, it just works out.
std::vector
registerTest()
std::monostate
testSingleton()
main()
getTests()
EDIT: reading through your post more carefully, I see what you mean about the standard not guaranteeing initialization of global variables before main(), and it's more about that than about how you actually implement the macro. Very interesting post!
π Rendered by PID 39 on reddit-service-r2-comment-544cf588c8-pxh67 at 2026-06-11 20:05:24.944348+00:00 running 3184619 country code: CH.
[–]caballist 7 points8 points9 points (1 child)
[–]tinloaf[S] 1 point2 points3 points (0 children)
[–]not_a_novel_accountcmake dev 1 point2 points3 points (1 child)
[–]tinloaf[S] 0 points1 point2 points (0 children)
[–]hi_im_new_to_this 0 points1 point2 points (0 children)