C++ 在成员初始值设定项中创建临时对象时销毁它的点 #包括 结构A{ A(整数){ } ~A(){ 标准::cout
Clang是正确的,但是是的,标准可能更清晰 (通过引用绑定临时延长表达式生存期)的影响是为了确保除列出的例外情况外,绑定到引用的临时变量的生存期延长到引用的生存期。但是,当引用是类非静态数据成员时,在绑定点(在(可能默认的)构造函数中发生这种情况)引用的生存期不是静态已知的,因此,将临时成员的生存期延长是不合理的。由于非静态数据成员不包括在例外列表中,因此必须通过其他方式防止这种情况,事实上,在以下情况下,IF可以防止这种情况: 8-绑定到mem初始值设定项中引用成员的临时表达式格式不正确 11-从默认成员初始值设定项绑定到引用成员的临时表达式格式错误 我们必须得出这样的结论:这种语言的目的是使任何试图从类的(可能是默认的)构造函数中将临时对象绑定到类数据成员的行为都是格式错误的,因为否则临时对象将有资格进行生存期扩展,这将是毫无意义的(引用的生存期是静态未知的)。因此,这必须包括子集料的参考构件;本标准宜包括一个说明 值得注意的是,将临时表达式绑定到参考文献中,如低于3例:C++ 在成员初始值设定项中创建临时对象时销毁它的点 #包括 结构A{ A(整数){ } ~A(){ 标准::cout,c++,gcc,clang,language-lawyer,C++,Gcc,Clang,Language Lawyer,Clang是正确的,但是是的,标准可能更清晰 (通过引用绑定临时延长表达式生存期)的影响是为了确保除列出的例外情况外,绑定到引用的临时变量的生存期延长到引用的生存期。但是,当引用是类非静态数据成员时,在绑定点(在(可能默认的)构造函数中发生这种情况)引用的生存期不是静态已知的,因此,将临时成员的生存期延长是不合理的。由于非静态数据成员不包括在例外列表中,因此必须通过其他方式防止这种情况,事实上,在以下情况下,IF可以防止这种情况: 8-绑定到mem初始值设定项中引用成员的临时表达式格式不正确 1
main
A(int)
~A()
B(int)
D()
exit
~B()
一个有趣的情况是,包含引用非静态数据成员的类是聚合,因此通过列表初始化语法(示例改编自):
尽管gcc和MSVC错误地接受,#1
和#4
格式不正确。#3
根据[class.base.init]/11标准的当前措辞格式不正确,但这与委员会的意图相反,如下所述:
2014年2月会议记录:
CWG同意建议的方向,即将示例中的#3视为#2,并删除默认构造函数
也就是说,#3
将是有效的,并导致生存期延长;奇怪的是,clang报告了一个诊断,声称尽管这样做,它仍不会执行生存期延长!:
警告:抱歉,不支持使用默认成员初始值设定项通过聚合初始化创建的临时项的生存期扩展;临时项的生存期将在完整表达式[-Wdangling]的末尾结束
我已经问过了
请注意(假设这是允许的)它只起作用,因为
c3
是一个完整的对象;如果它是一个成员对象(如第一个示例中的c
)[class.base.init]将最终应用,c3
也将是格式错误的。它是c{0}
导致问题的原因-使用对临时a
对象的引用初始化c
的a
成员。@1201程序是否导致任何问题?是否违反任何规则?c{0}
将执行聚合初始化。这里的关键点是临时A
object@1201ProgramAlarm我不确定你是否提到了。这个案例也不是例外,它有正确的行为来销毁临时对象。段落[class.temporary]中的措辞在哪里/6提到了这一点:“当绑定到临时对象的引用是存在于函数作用域中的对象时(因此具有直到其作用域结束的生存期,由大括号或控制流构造分隔),或者在命名空间作用域中(因此具有整个程序生存期),就会发生此生存期扩展。”尽管它可以直观地理解,但是相关的措辞在哪里?@jackX谢谢,我重新修改了我的答案。你能再看一看吗?我认为c3
仍然应该是无效的,因为它遵守了。也就是说:如果元素有一个默认的成员初始值设定项([class.mem]),那么元素是从该初始值设定项初始化的。因此,[class.base.init]/11在这里也适用。@jackX是一个非常好的观点,但有点令人困惑。CWG 1815上的注释说,在Issaquah(2014-02),CWG决定使代码c3{}
格式良好;然后在Rapperswil(2014-06)该DR被CWG 1696决议标记为已解决,但采用的语言没有给出一个示例,说明该案例是否被允许,而且使c3{}
书面形式不正确,但CWG的意图肯定很重要,更不用说实施实践了?我会更新我的答案并继续跟进。问:
main
A(int)
~A()
B(int)
D()
exit
~B()
struct A {};
struct C { A&& a = A{}; };
C c1; // #1
C c2{A{}}; // #2
C c3{}; // #3
C c4 = C(); // #4