问候,大家!
检查我自己的代码,我走到了这个有趣的路线:
const CString &refStr = ( CheckCondition() ) ? _T("foo") : _T("bar");
现在我完全不知所措,无法理解为何合法。据我所知,必须使用r值或l值初始化const引用。未初始化的引用不可存在。但是()? operator在为引用赋值之前执行CheckCondition()函数。我现在可以看到,当执行CheckCondition()时,refStr存在,但仍未初始化。如果CheckCondition()将抛出异常,或使用goto语句传递控件,会发生什么?它是否会使参考文献未初始化或者我遗失了什么?
答案 0 :(得分:6)
你遗漏了一些东西 - 它是完全合法的代码,事实上这样的代码是条件运算符最常用和最好的用法之一。认为编译器必须在内部以与代码在页面上布局相同的顺序执行操作总是错误的 - 完全可以自由地评估条件运算符(这只是另一个表达式),然后使用结果执行初始化。
至于goto,在初始化中无法使用它。如果抛出异常,则认为引用从未在第一时间创建。
答案 1 :(得分:5)
更简单的例子:const int x = foo();
此常量也必须初始化,并且需要调用foo()
。这种情况按照必要的顺序发生:只有当foo返回时,x才会存在。
要回答您的其他问题:如果foo()
throw
catch()
,则异常将由try{}
某地抓住。 catch()
的{{1}}块明显包围const int x = foo();
。因此const int x
已超出范围,并且它永远不会有价值无关紧要。如果异常没有catch
,那么您的程序(包括const int x
)就会消失。
C ++没有随机goto
。他们可以在foo()
内跳,但这并不重要; foo()
仍然需要返回。
答案 2 :(得分:3)
未初始化的引用不存在。
不幸的是,有趣的事情可以在初始化期间完成。你也可以写
const int& a = foobar(a) ? 1 : 2;
或者此事
const int& a = a;
我想,当编译器从左到右进行时,a确实在右侧的范围内,所以技术上你应该能够使用它,并且它最多可以发出警告:
“ComeauTest.c”,第9行:警告:在设置值之前使用变量“a”
const int& a = foobar(a) ? 1 : 2;
^
当然,这只会导致未定义的行为,就像使用任何未初始化的变量一样。
您的示例很好,因为您在初始化之前不使用该引用。
答案 3 :(得分:2)
我现在可以看到,当执行CheckCondition()时,refStr存在,但仍未初始化。
从语言律师的角度来看,这是错误的。在初始化期间,refStr
尚不存在。我猜你的视觉调试器会给你带来误导性的暗示。
如果初始化中的代码导致错误情况,refStr
将不存在,并且永远不会存在。
答案 4 :(得分:2)
这是完全合法的。要么成功完成并且引用绑定到有效对象,或者抛出异常并且控制转移到块外部,并且引用不再在范围内,因此不再关心它。
答案 5 :(得分:0)
异常会将您带到一个无法访问refStr的地方,您无法从那里前往某个地方。如果它是一个函数,goto将无法退出CheckCondition(),如果它是一个宏,你将无法使用goto。 longjmp()将具有与异常相同的效果:您将转到无法访问refStr的位置。