C++大括号初始化时引用父对象、传递封闭对象引用是否安全?
关于C++大括号初始化中引用未完全构造对象的安全性问题
针对你提出的问题,结合给出的代码示例,解答如下:
核心结论
在你提供的代码场景中,这种用法是安全的,但安全性取决于子对象构造函数的具体行为,核心规则是:只要不访问未初始化的成员,引用正在构造的父对象就是合法的。
具体分析
引用绑定的合法性
当执行Foo f{ .b = Bar{f} }时,f是正在构造的对象,它的内存空间已经被分配完成,只是尚未完成全部成员的初始化。C++标准允许将引用绑定到这种“正在构造中”的对象上,因为引用只需要关联到已分配的存储,不需要对象完全构造完成。子对象构造时的风险边界
你的代码中Bar的构造函数是空实现,没有访问Foo的任何成员,因此不存在任何风险。但如果Bar的构造函数尝试访问Foo的成员,就需要注意:- 如果访问的是
Foo中已经完成初始化的成员(比如Foo的成员声明顺序在b之前),则操作合法; - 如果访问的是
Foo中尚未初始化的成员(比如Foo的成员声明顺序在b之后),则会触发未定义行为,这是绝对禁止的。
- 如果访问的是
举个反例说明风险:
struct Foo; struct Bar { Bar(Foo& f) { // 这里访问f.x,但x在Foo中是b之后的成员,此时x未初始化,属于未定义行为 int val = f.x; } }; struct Foo { Bar b; int x; // 声明顺序在b之后,初始化晚于b }; int main() { Foo f{ .b = Bar{f} }; }
- 大括号初始化的特殊注意点
聚合初始化(这里Foo是聚合类型)的顺序严格按照成员的声明顺序执行。在你的示例中,Foo只有Bar b一个成员,所以初始化b时,Foo的所有成员(仅b)正在被初始化,不存在未初始化的其他成员,因此完全安全。
内容的提问来源于stack exchange,提问作者user3001150
相关产品推荐
相关产品推荐

