C++ 抛出右旋值
以片段为例:C++ 抛出右旋值,c++,language-lawyer,c++14,throw,C++,Language Lawyer,C++14,Throw,以片段为例: try { Foo f; throw std::move(f); } catch (Foo& f) { } [expr.throw]说: 异常对象的类型 通过从操作数的静态类型中删除任何顶级cv限定符并调整 键入从“T数组”或“返回T的函数”到“指向T的指针”或“指向返回T的函数的指针”, 分别 这将是Foo&。然后根据[except.throw]初始化异常对象: 抛出异常副本会初始化(8.5,12.8)一个临时对象,称为异常对象。这个 temporary
try {
Foo f;
throw std::move(f);
}
catch (Foo& f) { }
[expr.throw]说:
异常对象的类型
通过从操作数的静态类型中删除任何顶级cv限定符并调整
键入从“T数组”或“返回T的函数”到“指向T的指针”或“指向返回T的函数的指针”,
分别
这将是Foo&
。然后根据[except.throw]初始化异常对象:
抛出异常副本会初始化(8.5,12.8)一个临时对象,称为异常对象。这个
temporary是一个左值,用于初始化匹配处理程序(15.3)中声明的变量。如果
异常对象的类型将是不完整的类型或指向不完整类型的指针,而不是
(可能cv合格)void
程序格式不正确
这向我建议将exception对象初始化为:
Foo&& __exception_object = std::move(f);
而且处理程序不匹配。然而,gcc和clang都捕获了这个异常。那么,这里异常对象的实际类型是什么?如果
Foo
,为什么?表达式的静态类型永远不是引用类型
1.3.24[定义静态类型]定义了“静态类型”:
在不考虑执行语义的情况下,通过分析程序得到的表达式类型(3.9)
“程序分析”的第一步是删除引用,请参阅
5[expr]p5和
如果表达式最初具有类型“reference toT
”(8.3.2,8.5.3),则在进行任何进一步分析之前,该类型将调整为T
。表达式指定由引用表示的对象或函数,表达式是左值或x值,具体取决于表达式
因此,std::move(f)
是一个xvalue表达式,具有静态类型Foo
您不需要使用右值来演示这一点,C++03中的情况也是如此:
int& f();
throw f();
这会抛出一个int
而不是int&
在不考虑细节的情况下,异常对象是对象,而引用不是对象,因此异常对象不能是引用。它一定是个物体