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?