Search code examples
c++value-initialization

c++: value initialization and default member initializer


struct MyType {
  const char *pointer{""};
};

struct MyTypeHolder {
 MyType my_type;

 MyType &GetMyType() { return my_type; }
};

int main () {
 MyTypeHolder my_type_holder;

 auto &my_type = my_type_holder.GetMyType();

 my_type = MyType{};

 // May one assert that my_type.pointer points to the empty string?
}

In the example above my_type = MyType{} a temporarily object of type MyType is value initialized. Because MyType has a default member initializer for a non-static member, can one assert that the pointer points to an empty string once the object is value initialized?


Solution

  • I'll assume C++14 or later for the answer. It was a bit different before that in terms of the formal rules, but with the same practical result.


    In the example above my_type = MyType{} a temporarily object of type MyType is value initialized.

    No, the temporary is aggregate-initialized, because you use curly braces and MyType is an aggregate type (as it doesn't have any user-declared constructors and satisfies all other requirements of an aggregate class).

    This means that no constructor is called (in contrast with value-initialization with parentheses which will call the implicitly-defined default constructor). Instead the pointer member of the temporary object is directly initialized with its default member initializer in the context of main, because there is no explicit initializer for it given in the braced initializer list from which the object is aggregate-initialized.

    The effect is however the same: pointer of the temporary will point to an string literal object holding an empty string and after assigning to my_type with the implicitly-defined move constructor, my_type.pointer will also point to the same string literal object.

    However, be aware that there is no guarantee that evaluating the string literal multiple times will yield a pointer to the same string literal object. This is completely up to the compiler.

    So, yes you can assert(my_type.pointer[0] == '\0');, but not assert(my_type.pointer == ""); or that two pointer obtained in this way hold the same address.