Path: csiph.com!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c++ Subject: Re: Global const objects missing from object file Date: Fri, 29 Oct 2021 06:29:35 -0700 Organization: A noiseless patient Spider Lines: 83 Message-ID: <861r44ez7k.fsf@linuxsc.com> References: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: reader02.eternal-september.org; posting-host="b7f56eff5ad6c7d9130605d054ce58ef"; logging-data="5278"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/xZp+BwuQZtlsEKf6bihsJZcIB31JSG6k=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:EQ5hsn8GAcZWi6757d4FQZFFpOY= sha1:R4fJ1u4J8bja7DFbPzqRJANLqII= Xref: csiph.com comp.lang.c++:82173 Paavo Helde writes: > 10.10.2021 09:55 Steve Keller kirjutas: > >> Paavo Helde writes: >> >>> Such global const definitions normally appear in a common header file >>> and would just cause duplicate linker symbols if they had external >>> linkage. Now they can be just optimized away in translation units >>> which do not use them. >>> >>> I believe the original motivation was to have an easy replacement of C >>> macros in header files, i.e. instead of >>> >>> #define a 42 >>> >>> one can easily use >>> >>> const int a = 42; >>> >>> which would function almost exactly like a #define, plus it honors C++ >>> namespaces and cannot be undefined. >> >> If you write such "global" const objects into a header file they are >> in fact not global, because the implicit 'static' makes them local to >> file translation unit and this can even cause duplication: >> >> $ cat foo.hh >> const int a = 42; >> const int *bar(); >> $ cat x.cc >> #include "foo.hh" >> const int *bar() { return &a; } >> $ cat y.cc >> #include >> #include "foo.hh" >> const int *foo() { return &a; } >> int main() >> { >> std::cout << (void *)foo() << '\n' << (void *)bar() << '\n'; >> } >> $ g++ -Os -o foo x.cc y.cc >> $ ./foo >> 0x56027d731008 >> 0x56027d731004 >> >> For a small 'int' one may not care but for larger constant objects >> this may be really bad. > > The unused const objects are routinely optimized away be the compiler, > as you saw by yourself ("object file was empty"). > > It's true that for larger and more complicated objects this might not > work so well. So don't do that. Put the object in a single TU and > provide functions to access it. (Making the object extern is not safe > in general because of the "Static Initialization Order Fiasco".) > >> To avoid it, I think you still have to write the defintion into only >> one C++ source file using 'extern' >> >> extern const int = 42; >> >> and put >> >> extern const int a; >> >> into the header file. I still don't see the advantage for C++ to >> differ from C here. > > In some sense the do not differ. The const globals in C++ are > primarily meant for replacing C #define. Each C #define is TU-specific > and gets fully preprocessed by the preprocessor, no other TU-s are > involved. It appears you have sidestepped the central question here. What a definition like 'const int foo = 7;' (without any mention anywhere of 'extern') does in C++ is, AFAICT, exactly the same as a similar definition with static, namely 'static const int foo = 7;'. If these two definitions are exactly the same (and I believe they are), why change the meaning of the version that doesn't say 'static'? Why introduce what appears to be a gratuitous incompatibility with C when there was already a perfectly good construct that could be used (and works in C++ now) for defining a local constant?