c++ 投掷活动物体

栏目: C++ · 发布时间: 6年前

内容简介: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++ 投掷活动物体》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

SQL必知必会

SQL必知必会

福达 (Ben Forta) / 钟鸣、刘晓霞 / 人民邮电出版社 / 2013-5-1 / 29.00元

SQL语法简洁,使用方式灵活,功能强大,已经成为当今程序员不可或缺的技能。 本书是深受世界各地读者欢迎的SQL经典畅销书,内容丰富,文字简洁明快,针对Oracle、SQL Server、MySQL、DB2、PostgreSQL、SQLite等各种主流数据库提供了大量简明的实例。与其他同类图书不同,它没有过多阐述数据库基础理论,而是专门针对一线软件开发人员,直接从SQL SELECT开始,讲述......一起来看看 《SQL必知必会》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具