内容简介:http://stackoverflow.com/questions/6352438/throwing-movable-objects本站文章除注明转载外,均为本站原创或编译转载请明显位置注明出处:c++ 投掷活动物体
我注意到,当抛出的类型是可移动的时候,MSVC和g如何处理临时异常对象的创建,这一点略有不同.狩猎这些引起了额外的问题.
在进一步之前,这里是我的问题的核心:在复制/移动精灵的缺点中,标准人员是否说明如何创建临时异常对象?目前,我能做的最好的是从15.1 / 3以下引用:
A throw-expression initializes a temporary object, called the exception object, the type of which is determined by removing any top-level cv-qualifiers from the static type of the operand of throw and adjusting the type from “array of T” or “function returning T” to “pointer to T” or “pointer to function returning T”, respectively.
我猜这个答案被埋在别的语言的某个地方,定义了一个表达式的类型,以及对象的初始化,但是我没有运气拼接在一起.当抛出一个对象时,异常对象是否得到(a)复制构造,(b)适当地移动构造,否则复制构造,或者(c)以实现定义的方式初始化?
请考虑以下代码:
#include <iostream> using std::cout; using std::cin; using std::endl; struct Blob { Blob() { cout << "C" << endl; } Blob(const Blob&) { cout << "c" << endl; } Blob(Blob&&) { cout << "m" << endl; } Blob& operator =(const Blob&) { cout << "=" << endl; return *this; } Blob& operator =(Blob&&) { cout << "=m" << endl; return *this; } ~Blob() { cout << "~" << endl; } int i; }; int main() { try { cout << "Throw directly: " << endl; throw Blob(); } catch(const Blob& e) { cout << "caught: " << &e << endl; } try { cout << "Throw with object about to die anyhow" << endl; Blob b; throw b; } catch(const Blob& e) { cout << "caught: " << &e << endl; } { cout << "Throw with object not about to die anyhow (enter non-zero integer)" << endl; Blob b; int tmp; cin >> tmp; //Just trying to keep optimizers from removing dead code try { if(tmp) throw b; cout << "Test is worthless if you enter '0' silly" << endl; } catch(const Blob& e) { cout << "caught: " << &e << endl; } b.i = tmp; cout << b.i << endl; } }
这是在 ideone 上重新创建的.正如你所希望看到的,gcc通过ideone在第一种情况下创建了Blob对象,并在第二种情况下移动.结果总结如下,指针值替换为标识符.
Throw directly: C {A} caught: {A} ~ {A} Throw with object about to die anyhow C {A} m {B} <- {A} ~ {A} caught: {B} ~ {B} Throw with object not about to die anyhow (enter non-zero integer) C {A} m {B} <- {A} caught: {B} ~ {B} 2 ~ {A}
在MSVC2010中相同的代码,无论优化设置如何,结果是一样的,除了两个动作是副本.这是最初引起我注意的区别.
我假设的第一个测试是罚款;其经典版复印.
在第二个测试中,gcc的行为方式与我预期的一样.临时Blob被视为一个x值,异常对象由它移动构造.但是我不知道编译器是否需要识别原始的Blob是否到期;如果不是,则MSVC在复制时正常运行.因此,我的原始问题:标准授权在这里发生了什么,还是只是执行定义的行为继承异常处理的一部分?
第三个测试正好相反:MSVC行为我的直觉要求. gcc选择从b移动,但是b仍然存在,这在我处理抛出的异常之后继续使用它的事实证明了这一点.显然,在这个微不足道的例子中,移动或复制对b本身没有任何影响,但是当考虑重载分辨率时,肯定不允许编译器查看.
显然,复制/移动检测的存在使得这个简单的测试很难推广,但更大的问题是,编译器可能不会简单[特别是在第三次测试的gcc和一般的MSVC的情况下].
注意这完全是为了学术目的;我几乎不会抛出任何东西,除了一个临时的,这两个编译器构造在任何地方,我相当确定行为是允许的.
移动行为符合案例2,但不符合案例3.参见12.8 [class.copy] / p31:
When certain criteria are met, an
implementation is allowed to omit the
copy/move construction of a class
object, even if the copy/move
constructor and/or destructor for the
object have side effects. …
…
-
in a throw-expression, when the operand is the name of a non-volatile
automatic object (other than a
function or catch-clause parameter)
whose scope does not extend beyond the
end of the innermost enclosing
try-block (if there is one), the
copy/move operation from the operand
to the exception object (15.1) can be
omitted by constructing the automatic
object directly into the exception
object
上面没有定义何时可以隐式地移动对象.但是它确实定义了复制/移动检查是否合法.当隐含的移动是合法的时候,你必须参考同一节中的第32段:
32 When the criteria for elision of a copy operation are met or would be met save for the fact that the source object is a function parameter, and the object to be copied is designated by an lvalue, overload resolution …
本段解释说,当复制/移动检测是合法的时候,过载解决会发生两次:
>首先假设lvalue是决定什么构造函数被调用或被删除的值.
>如果1)失败,则以参数作为左值重复重载解析.
这具有从最差到最差产生移动语义层次结构的效果:
>如果你可以去施工,就这样做.
>否则,如果你可以移动对象,这样做.
>否则可以将对象复制出来,这样做.
>否则发出诊断.
请注意,这些本质上是与普通返回本地堆栈对象相同的规则.
http://stackoverflow.com/questions/6352438/throwing-movable-objects
本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:c++ 投掷活动物体
以上所述就是小编给大家介绍的《c++ 投掷活动物体》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 旷视发布通用物体检测数据集 Objects365,开启 CVPR 物体检测挑战赛
- WebGL之物体选择
- 简易版物体识别
- 精准快速的物体分割算法
- 半透明物体如何实现阴影效果?
- 深度有趣 | 11 TensorFlow物体检测
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。