26

Is the default initialization/construction of enum classes defined behavior?

Here is a minimal example(Try Online)

enum class ALPHA{
    X = 0,
    Y = 1,
    Z = 2,
};

int main()
{
    ALPHA a = ALPHA(); // use default constructor
    ALPHA b{}; // use default initialization
    std::cout <<static_cast<int>(a) << std::endl; // 0
    std::cout <<static_cast<int>(b) << std::endl; // 0
    return 0;
}

I get zero in both cases. So does the default initialization pick the first enum type(eg. here X = 0) always? I know that it is UB for standard enums but Im not sure about the semantics for enum classes? I looked this up on CPPReference too but didnt find any relevant information about it - Is it possible to get a standard reference too?

8
  • 1
    Is this a duplicate of stackoverflow.com/questions/17630967/…? I think at least that answer also answers your question. Commented Dec 22, 2018 at 17:51
  • 1
    I think it does somewhat answer my question - that theres no default constructor defined and this case will default initialize according to int- but (1) there is no standard reference (2) is it guaranteed to default initialize according to the native type(stackoverflow.com/questions/3803153/…) Commented Dec 22, 2018 at 17:56
  • 1
    The sections he mentions are from the standard. What kind of reference are you looking for? Commented Dec 22, 2018 at 18:05
  • My bad - ok then I think that answers the question. Should I just delete this? Commented Dec 22, 2018 at 18:14
  • 1
    Now that I have looked at some different versions of the standard, I see that there has been a change on this point. Apparently C++03 said zero-initialized where C++11 says it's uninitialized. I don't have official releases of the standards to check exactly which versions specify what. Commented Dec 22, 2018 at 18:24

2 Answers 2

16

[expr.type.conv]/1 A simple-type-specifier (10.1.7.2) or typename-specifier (17.6) followed by a parenthesized optional *expression-list or by a braced-init-list (the initializer) constructs a value of the specified type given the initializer.

[expr.type.conv]/2 ... Otherwise, the expression is a prvalue of the specified type whose result object is direct-initialized (11.6) with the initializer.


[dcl.init]/(17.4) — If the initializer is (), the object is value-initialized.


[dcl.init]/8 To value-initialize an object of type T means:

(8.4) — otherwise, the object is zero-initialized.


[dcl.init]/6 To zero-initialize an object or reference of type T means:

(6.1) — if T is a scalar type (6.9), the object is initialized to the value obtained by converting the integer literal 0 (zero) to T


[basic.types]/9 ... enumeration types ... are collectively called scalar types.

Put together, ALPHA() is equivalent to static_cast<ALPHA>(0)

Sign up to request clarification or add additional context in comments.

5 Comments

I'm not sure if this answers the question "Is the default initialization/construction of enum classes defined behavior?". ALPHA() isn't default initialization, it's value initialization, same as ALPHA b{}. What would happen with ALPHA c;?
@ctn Uninitialized, same as, say, int d;
Thanks. Could you add a mention of this in your answer please? I think it would be appropriate given the wording of the question, but more importantly: I briefly looked and haven't found a SO question with an answer that addresses this, and other people will also run across this answer when searching for default initialization of enum classes.
@Igor Tandetnik ALPHA() is equivalent to static_cast<ALPHA>(0). What would happen if none of the enumerators is equivalent to 0? Say enum class ALPHA{ x=1;y=2;z=3;}
@John Then you would have a value not equal to any of x, y or z. Nothing says that a value of enum type must always match one of the enumerators.
5

enumeration with fixed underlying type can be initialized by initializer-list if it's in the context of direct initialization and the initializer-list contains a single element with no narrowing conversion involved.

[dcl.enum]/8

[...] It is possible to define an enumeration that has values not defined by any of its enumerators.

[dcl.init]/6.1

To zero-initialize an object or reference of type T means:

(6.1) if T is a scalar type, the object is initialized to the value obtained by converting the integer literal 0 (zero) to T

That said, it's possible to have an enumeration initialized with values that is not in the range of its enumerators, but when it does fall in range, then it correspond to the enumerator.

In your example, the zero initialization initialize a and b to with 0 which correspond to the enumerator X, meaning... your example is well defined.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.