C++:值初始化和默认成员初始值设定项

Tru*_*uLa 1 c++ value-initialization

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?
}
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,my_type = MyType{}类型的临时对象MyType被值初始化。因为MyType非静态成员有一个默认的成员初始值设定项,pointer所以一旦对象被值初始化,就可以断言 指向空字符串吗?

use*_*522 5

我假设 C++14 或更高版本作为答案。之前的形式规则略有不同,但实际结果相同。


在上面的示例中,my_type = MyType{} 对 MyType 类型的临时对象进行了值初始化。

不,临时是聚合初始化的,因为您使用花括号并且MyType是聚合类型(因为它没有任何用户声明的构造函数并满足聚合类的所有其他要求)。

这意味着不调用任何构造函数(与带括号的值初始化相反,它将调用隐式定义的默认构造函数)。相反,pointer临时对象的成员在 的上下文中直接使用其默认成员初始值设定项进行初始化main,因为在聚合初始化对象的大括号初始值设定项列表中没有给定它的显式初始值设定项。

然而,效果是相同的:pointer临时的将指向一个包含空字符串的字符串文字对象,并且在my_type使用隐式定义的移动构造函数分配给后,my_type.pointer也将指向相同的字符串文字对象。

但是,请注意,不能保证多次计算字符串文字会产生指向同一字符串文字对象的指针。这完全取决于编译器。

所以,是的,你可以assert(my_type.pointer[0] == '\0');,但不能assert(my_type.pointer == "");或者以这种方式获得的两个pointer拥有相同的地址。