下面这段代码的输出不如预期:
#include<iostream>
using namespace std;
struct student {
char name[20];
int score;
};
int main(int argc, char argv[]) {
student st1{ "he", 23.0 };
student sts[2]{ { "H1",2 }, { "H2", 4 } };
student* p = new student{ "Jx", 4 };
student* ps = new student[2]{ { "pH1",2 }, { "pH2", 4 } };
cout << st1.name << endl;
cout << sts[0].name << endl;
// 动态分配结构对象,可以初始化
cout << p->name << endl;
cout << p->score << endl;
// 动态分配结构数组,初始化无效,但是语法不报错
cout << ps[0].name << endl;
cout << ps[0].score << endl;
}
输出结果是这样的:
通过new创建student结构数组时,通过大括号方式给出初始化值,没有成功,但是语法不报错。但是创建单个student对象时,缺成功初始化了。
如果将struct中的char name[20]替换为string name后,初始化成功了。
struct student {
string name;
int score;
};
原因可能跟编译器实现有关。
在linux下通过gcc编译时,new单个student对象时就报错了。
网上搜了下,大概了解了初始化列表的调用过程。
当使用{ }进行初始化,编译器看到{t1,t2…tn}时便做出一个initializer_list,它关联到一个array<T,n>。编译器会分析当前语句的语义,当构造数组对象时,将解析{{}}嵌套,该array内的元素可以被编译器分解,逐一传递给元素对象的构造函数。
例如:本例中new student [ ],{ }会形成一个initializer_list,背后有个array<student,2>,然后调用student的构造函数创建student对象,这个过程中通过ctor-initializer为student对象初始化。由于我们没有为student提供显示的构造函数,默认构造函数里的初始化器(ctor-initializer)可能无法处理const char* 到char []的转换。而当用string作为name数据项的类型时,构造-初始化过程中会调用string类的相关函数。(以上是我的猜测)