C++ Logo

std-discussion

Advanced search

Re: Zero-initialization in value-initialization of classes with defaulted default ctors

From: Anton Bikineev <ant.bikineev_at_[hidden]>
Date: Mon, 3 Feb 2020 13:53:58 +0100
>
> It seems to me that `optional` is not usable in compile-time before C++20,
> because switching union active member is not allowed, and so it doesn't
> make sense to mark `optional()` as constexpr, but maybe I have missed
> something.

That's a good point. Interestingly enough, the following code happened to
work on both gcc and clang with C++17:
* constexpr void foo() {*
* std::optional<int> opt;*
* opt = 2;*
* }*
yet it's clear that there is an "*invocation of an assignment operator that
would change the active member of a union*" (removed in p1330) in both
libstdc++ and libc++.

why in your initial example `dummy` is an array? If it's a single object,
> pessimization due to zero-initialization will be reduced

This code was minimized from the abseil's optional (
https://github.com/abseil/abseil-cpp/blob/master/absl/types/internal/optional.h#L79).
The comment there says that the reason is to avoid a gcc-warning.
Another reason (a bit technical and implementation specific) was that
having union members of different sizes were optimized by clang/llvm by
storing shared and non-shared parts of the union in separate memory
locations, which caused conservative garbage collection used in the
Chrome's renderer to miss the pointer stored in an optional.

If it's a single object, pessimization due to zero-initialization will be
> reduced

Having zero-initialization even for a single empty object is already
pessimization. We're just lucky that for a single object it gets optimized
away by clang, but at the same time are unlucky that for the whole array it
doesn't (as opposed to gcc).

It would be very strange if for the `pair<int, array<int, 1>> p;` p.first
> == 0, but p.second[0] has indeterminate value.

The example totally makes sense, thanks.

I think that technically even for a single empty object its 'value' may be
observable (e.g. through char* aliasing), but I don't think there is a real
use case for this, given that compilers already optimize such cases. I
wonder if it would make sense to expand the definition of empty class from
type traits to the Core to allow for more optimizations.


вс, 2 февр. 2020 г. в 11:11, Andrey Davydov <andrey.davydov_at_[hidden]>:

> On Sat, Feb 1, 2020 at 4:46 PM Anton Bikineev <ant.bikineev_at_[hidden]>
> wrote:
>
>> Or, even better, remove definition of `optional()` to make it
>>> trivially-default-constructible?
>>
>> Removing the definition of optional() (or in general having it not
>> user-provided) makes it deleted for T that have non-trivial default
>> constructor (since T is in union).
>>
>> but I still don't see a reason to value-initialize `dummy`.
>>
>> Value-initialization appears to be needed for the constructor to be
>> constexpr.
>>
> It seems to me that `optional` is not usable in compile-time before C++20,
> because switching union active member is not allowed, and so it doesn't
> make sense to mark `optional()` as constexpr, but maybe I have missed
> something.
> A slightly offtopic question: why in your initial example `dummy` is an
> array? If it's a single object, pessimization due to zero-initialization
> will be reduced (https://godbolt.org/z/PxDR8J).
>
> --
> Andrey Davydov
>


-- 
Sincerely,
Anton.

Received on 2020-02-03 06:56:45