代码之家  ›  专栏  ›  技术社区  ›  SadSido

C++中的参考初始化

  •  1
  • SadSido  · 技术社区  · 15 年前

    大家好!

    通过检查我自己的代码,我想到了一个有趣的行:

    const CString &refStr = ( CheckCondition() ) ? _T("foo") : _T("bar");
    

    现在我完全不知所措,无法理解为什么这是合法的。据我所知,常量引用必须用r值或l值初始化。未初始化的引用不能存在。但是(?)运算符在为引用赋值之前执行checkCondition()函数。现在我可以看到,在执行checkCondition()时,refstr存在,但仍然没有初始化。如果checkCondition()将引发异常,或者用goto语句传递控件,会发生什么?它是否会使引用未初始化,或者我是否缺少某些内容?

    6 回复  |  直到 15 年前
        1
  •  5
  •   MSalters    15 年前

    更简单的例子: const int x = foo();

    这个常量也必须初始化,为此 foo() 需要打电话。这是按照必要的顺序发生的:只有当foo返回时,x才会出现。

    回答您的其他问题:如果 英尺() throw ,异常将由 catch() 某处。这个 try{} 为那个街区 () 包围 const int x=foo(); 很明显。因此 const int x 已经超出了范围,而且与它从未得到值无关。如果没有 catch 对于例外情况,您的程序(包括 常量x 消失了。

    C++没有随机性 goto 是的,他们可以跳进去 英尺() 但这并不重要; 英尺() 还得回去。

        2
  •  6
  •   anon    15 年前

    您缺少了一些东西——这是完全合法的代码,事实上,这种代码是条件运算符最常见和最好的用法之一。如果认为编译器必须在内部按代码在页面上的布局顺序执行操作,那总是一个错误——可以完全自由地计算条件运算符(这只是另一个表达式),然后使用结果执行初始化。

    对于goto,在初始化时无法使用。如果抛出了一个异常,那么首先就认为从未创建过引用。

        3
  •  3
  •   UncleBens    15 年前

    未初始化的引用不能存在。

    不幸的是,在初始化期间可以做一些有趣的事情。你也可以写

    const int& a = foobar(a) ? 1 : 2;
    

    或者是为了这个问题

    const int& a = a;
    

    我想当编译器从左到右进行时,a确实在右边的作用域中,所以 技术上 您应该能够使用它,最多它可以警告:

    “comeautest.c”,第9行:警告:在设置变量值之前使用变量“a”

      const int& a = foobar(a) ? 1 : 2;
                            ^
    

    当然,这只能导致未定义的行为,就像使用任何未初始化的变量一样。

    您的示例很好,因为在初始化引用之前不使用它。

        4
  •  2
  •   Konrad Rudolph    15 年前

    现在我可以看到,在执行checkCondition()时,refstr存在,但仍然没有初始化。

    从语言律师的角度来看,这是错误的。初始化期间, refStr 还不存在。我猜你的可视化调试器给了你误导性的提示。

    如果初始化中的代码导致错误情况, 雷夫斯特 不会存在,也永远不会存在。

        5
  •  2
  •   sharptooth    15 年前

    这是完全合法的。要么成功完成,引用绑定到有效对象,要么抛出异常,并将控制权转移到块之外,引用不再在作用域内,因此没有人再关心它了。

        6
  •  0
  •   AProgrammer    15 年前

    一个例外会把你带到一个地方,那里的refstr是不可接近的,你不能去一个地方,它是从那里。如果goto是一个函数,它将无法退出checkCondition(),如果它是一个宏,则无法使用goto。longjmp()的效果与异常相同:您将去一个refstr不可访问的地方。