【问题标题】:Binding temporaries to non-const references in case of exceptions在异常情况下将临时对象绑定到非常量引用
【发布时间】:2014-11-07 17:33:54
【问题描述】:

我一直读到,在函数调用的情况下,临时变量只能与非常量引用参数绑定..

案例 1:-

例如:-

class Simple{
    public: 
       int i;
       Simple(Simple &f)
       {
         i = f.i + 1;
       }
       Simple(int j)
       {
         i = j;
       }
  };

int main()
{
   Simple f1 = Simple(2);   // error no matching call fruit::fruit(fruit)...
   return 0;
}

这会给我一个错误,因为我试图用非常量引用参数绑定临时。

案例 2:-

try
{
 throw e;
}
catch ( exception& e )
{
}

我了解到,当我们抛出异常时,真正传递给 catch 的是抛出的原始异常的副本,即为抛出的对象创建一个临时对象,然后将其传递给 catch 子句。

catch 正在做的是通过非常量引用捕获这个异常。这与我在案例 1 中展示的情况形成鲜明对比。

所以,我的问题是:-

1) 是否存在允许将临时绑定到非常量引用的特定场景。

2) 如果存在,那么在允许这些例外情况时会考虑哪些因素。

【问题讨论】:

  • 他的意思是“不允许”,如代码示例所示。

标签: c++ temporary-objects


【解决方案1】:

是否存在允许将临时绑定到非常量引用的特定场景。

对于左值引用(即T& 类型)没有。您不能将临时值绑定到非 const 左值引用,因为修改像 42 这样的文字没有多大意义。它们可以绑定到 const 左值引用,因为这样就做出了 not 修改引用所绑定的对象的承诺。

它们实际上可以绑定到rvalue-references (T&&),但这与此线程无关。

如果存在,那么在允许这些例外情况时会考虑哪些因素。

确实,临时对象不能绑定到非 const 左值引用,但对异常对象有一定的规定:

取自 C++11 标准(最接近的草案n3337):

§15.1/3 throw-expression 初始化一个临时对象,称为 异常对象,其类型是通过从 throw 的操作数的静态类型中删除任何顶级 cv 限定符来确定的 并将类型从“T 数组”或“函数返回 T”调整为 分别是“指向 T 的指针”或“指向返回 T 的函数的指针”。 该 临时是一个左值,用于初始化命名的变量 匹配的处理程序 (15.3)。 [..]

强调我的

cppreference 将其简化为:

与其他临时对象不同,异常对象在初始化catch子句参数时被认为是一个左值参数,因此可以被左值引用捕获、修改和重新抛出。

因此,对于这种情况,您实际上可以将异常绑定到非 const 左值引用。

【讨论】:

  • 是的,我知道有异常的情况下是有异常的。但这是我的问题,它选择的理由是什么,或者还有其他类似的例外......
  • @ravi 做出此规定的原因是允许修改和重新抛出异常,正如它所说的那样。我不知道这条规则有任何其他例外情况。
  • @ravi The resolution to core issue 1299 听起来可能会回答你的问题。
  • @0x499602D2 很好的答案,我刚才在想这个,赞成
  • “修改像 42 这样的文字没有多大意义。” 为什么在抛出 42 作为异常时这不适用?我不明白为什么在异常上下文中使用文字时修改文字(我猜是临时初始化为文字的值)更有意义。
猜你喜欢
  • 2012-02-25
  • 2022-01-01
相关资源
最近更新 更多