2015-07-20 90 views
2

这是否适合作为异常处理程序,其中T是某类的非const成员函数func通过const引用捕获异常并抛弃const

换句话说:catch保证直接绑定到(可修改的)异常对象,还是有编译器在你通过const引用捕获时做一些欺骗的自由度?

catch(const T &t) 
{ 
    const_cast<T &>(t).func(); 
} 
+1

Whyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy? –

+0

@dufresnb:绝对没有理由写这样的代码。 –

回答

5

从[except.throw]:

评价犯规表达中的操作数将抛出异常(15。1);异常对象 的类型是通过从操作数的静态类型中除去任何顶级cv限定符并将“T的数组”或“返回T的函数”的类型调整为“指向T的指针”或“指向函数返回T“,分别为 。

和,重点煤矿:

抛出异常拷贝初始化(8.5,12.8)的临时对象,称为异常对象。 临时是一个左值并用于初始化匹配处理程序(15.3)中声明的变量。

因此,如果我们抛型CV T的操作,我们复制初始化类型T的临时对象

然后按[except.handle],为常量T A处理器&(对于非指针式t)是E型的异常对象匹配,如果:

  • [...] E和T为相同类型(忽略顶层CV-限定符),
  • [...] T是一个明确的公共基地类E

该处理程序由初始化:

类型CV由异常声明声明的变量, T或CVŤ&,从异常 对象初始化,类型E,如下:
- 如果T是一个基类E中,variab le从异常对象的相应基类子对象 中复制初始化(8.5)
- 否则,变量将从异常对象进行复制初始化(8.5)。

因此,如果我们以const赶上牛逼&,我们复制初始化从异常对象的引用 - 这是我们从上一节知道会是两种类型的T或者是由T公开来源于[ dcl.init.ref]:

的参考输入“CV1 T1”由类型的表达式“CV2 T2”如下初始化:
- 如果参考是一个左值和参考初始值表达式
    - 是左值(但不是位字段),并且“cv1 T1”与参考兼容“cv2 T2”,或[...]]

那么参考结合到初始化表达式左值在第一种情况下

的关键是,在临时异常对象仍然是一个左值。因此,如果我们的处理程序与const T &匹配,我们知道该参考直接绑定到类型为T或D的对象(其中D源自T) - 无论哪种方式,它都是与const T参考兼容的类型。因此,没有不确定的行为。如果临时对象是右值,或者处理程序可以匹配更多类型的类型,则会创建类型为const T的临时对象,并且您的const_cast肯定会是未定义的行为。

当你的代码显示出一个符合标准的编译没有未定义的行为,实在没有理由不只是做:

catch(T &t) 
{ 
    t.func(); 
} 
3

我没有看到标准中有任何“欺骗”的证据。无法证明是否定的,但我相信你是“安全”的。所述const岬似乎是形式等效于此:

T obj; 
const T& t = obj; 
const_cast<T &>(t).func(); 

即,const岬第一应运而生上catch块中存在的,就是这样的参考。

但是这一切都真的引发了一个问题:如果通过查看它无法确定,为什么要这么做呢?

只要赶上T&,当然。

0

,因为它说here

如果捕获子句的参数是一个参考的类型,它的任何更改都反映在异常对象,并且可以由另一个处理机如果异常可以观察到重新抛出;

所以这表明修改异常对象是安全的,并且这些更改是可观察的。

但是,应该考虑只是通过普通的参考来捕捉。或者,如果功能const只能用于标记为mutable的成员,则可以使用此功能。

任何这些都听起来不可读,并可能使合作开发商敌视。

+1

不是真的回答这个问题。 –

+0

这意味着如果您通过引用并重新引发,重新抛出的处理程序可以看到您的更改。这并不意味着修改'const&'所做的任何事情都可以。 –

+0

@LightnessRacesinOrbit问题是“保证直接绑定到(可修改的)异常对象的catch”。报价表明它是。 – BartoszKP

6

(我使用C++ 11;我需要更新;))

15.1/3(重点煤矿):

掷表达初始化一个临时对象,称为异常对象,其类型是通过从静态式抛的操作数的去除任何顶级CV-合格音响ERS

这意味着确定异常对象永远不是“天生的const”,因此不应触发未定义的行为进行修改。

+0

这看起来很确定;不错。 –

+1

FWIW在C++中的措辞是相同的14 –

+0

从技术上讲,这并不能证明ref绑定到上面定义的对象,并且没有“欺骗”,但是,正如在我自己的答案中,您不能否定否定。而且,为什么_它会以这种方式工作呢?这个问题不清楚我们需要反驳什么欺骗,所以...... –