- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我注意到当抛出的类型是可移动的时,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 via 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中相同的代码,无论优化设置如何,结果都是一样的,只是两个 Action 是拷贝。这是最初引起我注意的差异。
我假设的第一个测试很好;其经典的复制省略。
在第二个测试中,gcc 的行为符合我的预期。临时 Blob
被视为一个 xvalue,并且异常对象是从它构造的。但我不确定编译器是否需要识别原始 Blob
即将到期;如果不是,则 MSVC 在复制时 Action 正确。因此,我最初的问题是:标准是否规定了这里发生的事情,或者它只是异常处理所固有的实现定义行为的一部分?
第三个测试正好相反: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 ...
本段说明当复制/移动省略是合法的时,重载解决会发生两次:
首先假设左值是右值,以决定将调用或删除哪个构造函数。
如果 1) 失败,则将参数作为左值重复重载解析。
这会产生从最好到最坏的移动语义层次结构:
请注意,对于本地堆栈对象的普通返回,这些规则基本相同。
关于c++ - throw 可移动物体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6352438/
大家好,本文实现了相机碰撞检测,使相机不穿墙壁、物体,并给出了思路和代码,感谢大家~ 关键词:数字孪生、three.js、Web3D、WebGL、相机碰撞、游戏相机 我正在承接Web3D数字孪生项
我有一个大小为 12*30 的字符串的图像。我想创建一个动画,让它给人一种拉伸(stretch)字符串的感觉。我通过缩放图像来做到这一点,但我面临的问题是缩放图像没有发生碰撞。它仅出现在原始图像大小的
我的对象列表是如此初始化: $( function() { var $container = $('div.hikashop_products'); $container.isotop
我听说 swing 默认情况下是双缓冲的。我不想让 Swing 双缓冲。我正在使用双缓冲,我想添加一些 Swing 对象(现在只是添加到 JPanel 中的 JButton,然后再添加到 JFrame
几天来我一直在思考最好的解决方案,但似乎无法找到正确的想法。 我有一 block (物体),我想将它们放入尽可能小的空间中。我最终寻找的是这样的东西 http://i.stack.imgur.com/
我的纹理不仅仅是一个盒子或圆形,我的 body 需要与这个形状相同,所以我想结合多个 body 来达到我想要的形状,这甚至可能吗?或者有更好的方法吗?我正在使用带有 libgdx 框架的 java。
我遇到的情况是,我有很多计算机并且需要有唯一的 ID。 他们会通过 API 请求发送其 uniqueId。该对象看起来像 class ID { long timestamp; int id; }
我正在尝试检测一张卡片,但问题是有时图像不好并且有多个背景,如下所示: 没有很好地定义边缘 ![没有很好地定义边缘][1] 示例背景 ![示例背景][2] 我这样做了: gray = cv2.cvtC
我正在尝试从仅包含一辆车和简单背景的图像中分割汽车,如 但是我从我的实现中得到的是这个 和 分别 但它非常容易处理几乎已经分割的图像,例如。 给出类似 的结果 我使用的代码是 import cv2 i
我正在开发一个项目,在该项目中我从另一个对象/函数中引用一个变量。然而我总是返回 false。我不确定我是否正确调用它。 这是验证函数: app.validation = function(){
数组只是伪装的对象吗?为什么/为什么不呢?他们以什么方式(这样/不是)? 我一直认为 JS 中的数组和对象本质上是相同的,主要是因为访问它们是相同的。 var obj = {'I': 'me'}; v
我正在使用 PlayN 构建一个涉及石头的游戏,用户必须在物理世界中移动(通过重力等)。我希望用户能够使用触摸板直接操纵石头,并通过以下方式给它们一个速度拖拽并扔掷它们。 现在我有一个实现,其中每个石
http://jsfiddle.net/goldrunt/jGL84/42/这是来自这个 JS fiddle 的第 84 行。通过取消注释第 141-146 行,可以对球应用 3 种不同的效果。 'b
我学习Linux平台下的OpenGL。最近,我尝试使用 glutBitmapCharacter() 创建的文本作为 glu 或 glut 提供的一些二次对象的纹理。但是,glutBitmapChara
我正在使用 AndEngine 创建一个带有 box2d 扩展名的游戏。我想实现一个条件,当两个物体碰撞时,它们应该被移除或重生。最初我尝试使用 if(sprite1.collidesWith(spr
我制作了一个小型 3d 引擎。 但我在旋转功能方面遇到了一些问题。它们使物体不时拉伸(stretch)。这是数学: this.rotateX = function(angle) { var c
我在 Canvas 上制作了一个矩形 mask ,我需要 mask 外的任何东西都具有 0.8 的不透明度,因此 mask 外的所有对象都被视为不透明请看一下 fiddle 。 http://jsfi
我是 Direct3D 的新手,我在一个项目中从网络摄像头拍照并在它前面绘制一些 3D 对象。 我能够使用正交投影将网络摄像头图像渲染为背景。 //init matrix D3DXMatri
我是一名优秀的程序员,十分优秀!