C++ Logo

std-discussion

Advanced search

Re: Is [[indeterminate]] not applicable to data members?

From: Yongwei Wu <wuyongwei_at_[hidden]>
Date: Thu, 13 Mar 2025 12:16:01 +0800
On Wed, 12 Mar 2025 at 10:46, Yongwei Wu <wuyongwei_at_[hidden]> wrote:

> On Tue, 11 Mar 2025 at 23:11, Brian Bi <bbi5291_at_[hidden]> wrote:
>
>> On Tue, Mar 11, 2025 at 10:04 AM Yongwei Wu via Std-Discussion <
>> std-discussion_at_[hidden]> wrote:
>>
>>> On Mon, 10 Mar 2025 at 17:36, Giuseppe D'Angelo via Std-Discussion
>>> <std-discussion_at_[hidden]> wrote:
>>> >
>>> > On 25/02/2025 12:45, Yongwei Wu via Std-Discussion wrote:
>>> > > Currently, Obj::scratch_buffer will contain indeterminate values. In
>>> > > C++26, will there be a way for it to opt out of the erroneous value
>>> > > initialization, sans requiring the user to change the client-side
>>> > > code?
>>> >
>>> > I think there's a misunderstanding here: EB doesn't mandate that the
>>> > storage for an automatic variable gets initialized in any specific way.
>>> > It just changes the semantics of what happens if you read from an
>>> > uninitialized automatic variable (you get EB). The [[indeterminate]]
>>> > attribute restores the pre-C++26 semantics (you get UB).
>>>
>>> The problem is not the avoidance of UB, but the potential harm to
>>> performance. And I do not want the user to use the [[indeterminate]]
>>> attribute, which is awkward and simply wrong in semantics.
>>>
>>> > Do you have a use case for always wanting UB instead of EB for
>>> > uninitialized reads of a non-static data member?
>>>
>>> Was my example not good enough? OK, a more real one. But keep in mind
>>> I do not want UB, just that I do not want the compiler to initialize
>>> some uninitialized data members.
>>>
>>> I wrote a BigFixedString for test purposes, and google-benchmarked it.
>>> Two versions are posted online:
>>>
>>> https://quick-bench.com/q/9QkL9cSkqHSi2pb5A-TTkglbaDU
>>> https://quick-bench.com/q/MmE9IwFaXqjz_gFnEmSK8s3qFrA
>>>
>>> The difference is that one has a member `char buffer_[128];`, and the
>>> other `char buffer_[128]{};`. Of course, the uninitialized data are
>>> never read.
>>>
>>> Currently the benchmark results show the performance difference is
>>> about 90:54. Always initializing seems to have a 65% penalty on
>>> performance.
>>
>>
>> I'm uncomfortable with the idea of a class author being able to override
>> the user's choice to *not* declare a local variable [[indeterminate]],
>> by placing [[indeterminate]] on the declaration of a non-static data member
>> and thus making part of the object's storage indeterminate anyway. Note
>> that even if it's just in a private member, there will still be UB if the
>> object is used as the source of `memcpy`.
>>
>
> When a user writes `[[indeterminate]]`, it is their intention to exploit
> the potential efficiency of not initializing certain storage. When I, as
> class author, write `[[indeterminate]]` on data members, it is my intention
> (and responsibility) to exploit the efficiency and make sure I do not make
> mistakes.
>
> If a reasonable use of my code requires users to write
> `[[indeterminate]]`, it is an overburden for users. If they are cautious,
> they will have to check the implementation details of my class, which
> defeats the purpose of encapsulation.
>

Furthermore, I have the concern that erroneous behaviour, as it is
currently specified, may hinder the adoption of C++26, as it may slow down
certain applications, *without a proper way of remedy*. No, adding the
[[indeterminate]] attribute to class-type local objects is not a remedy,
but uglification. It is far too confusing to mark a class-type object with
proper constructors as [[indeterminate]].

I personally think it should be addressed in a new proposal, or maybe a
revised P2795? Opinions?

-- 
Yongwei Wu
URL: http://wyw.dcweb.cn/

Received on 2025-03-13 04:16:21