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?
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.
No, the temporary is aggregate-initialized, because you use curly braces and
MyTypeis 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
pointermember of the temporary object is directly initialized with its default member initializer in the context ofmain, 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:
pointerof the temporary will point to an string literal object holding an empty string and after assigning tomy_typewith the implicitly-defined move constructor,my_type.pointerwill 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 notassert(my_type.pointer == "");or that twopointerobtained in this way hold the same address.