问题标签 [rvalue-reference]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - 自动变量的复制删除以返回
我想知道当复制省略发生时,是否在 C++0x “ 12.8复制和移动类对象 [class.copy] 第 31 段”中:
当满足某些标准时,允许实现省略类对象的复制/移动构造[...]。这种复制/移动操作的省略,称为复制省略,在以下情况下是允许的 [...]:
- 在具有类返回类型的函数的返回语句中,当表达式是具有与函数返回类型相同的 cv 非限定类型的非易失性自动对象 [...] 的名称时,复制/移动操作可以通过将自动对象直接构造到函数的返回值中来省略
- [...]
现在我想知道,这是否允许在以下代码中逃避复制
还是该规则不适合示例,我必须明确说明?
请注意,我的意图if
是消除明显的返回值优化(RVO)。
还是我在这里完全走错了路?有一个涉及return
和move的更改可以使用rvalue references,对吗?
c++ - 在构建复合对象时消除不必要的副本
我正在考虑开发一些命名参数代码,但它让我想到了一些如下代码:
现在,一个天真的实现会首先执行“make_pair(4,5)”,然后将结果复制到“make_pair(3, ...)”的第二个元素中,然后将其复制到“make_pair”的第二个元素中(2, ...)”等。
不幸的是,这将导致 O(n^2) 性能,并带有很多不必要的副本。我也看不出(命名的)返回值优化在这里有什么帮助。
理想情况下,make_pair(4,5)
意识到它将在 的最后一个位置x
,并在那个位置构建自己。
更进一步:
我也想避免在这样的代码中复制。
这种优化是否如此明显以至于我应该假设编译器会执行它,或者是否有另一种方式我应该对其进行编码以避免复制?
c++ - 运算符重载,允许使用右值捕获但不分配给
是否可以设计以及我应该如何让operator+
我的班级重载C
才能实现这一点:
但这不可能:
编辑:我将对象更改为小写字母。c1
,c2
并且c
是类的对象C
。&&
不是逻辑的operator&&
,而是右值引用。
例如写作:
是 100% 正确的(新)C++ 代码,而
显然是编译器错误。对于我的班级,我想要完全相同,但要加倍C
。
第二次编辑: 如果我的运算符返回 C 或 C&,我可以赋值给右值引用,也可以赋值给 c1 + c2,这是没有意义的。在这里给出 const 会禁用它,但是它也会禁用对右值的分配。至少在 VC++ 2k10 上。那么这个是多少倍呢?
c++ - 如何真正实施五法则?
更新在底部
q1:对于管理相当大量资源的类,您如何实现五规则,但您希望它通过值传递,因为这大大简化和美化了它的使用?或者甚至不需要规则的所有五项?
在实践中,我开始使用 3D 成像,其中图像通常是 128*128*128 双倍。能够写出这样的东西会使数学变得容易得多:
q2:使用复制省略/RVO/移动语义的组合,编译器应该能够以最少的复制来实现这一点,不是吗?
我试图弄清楚如何做到这一点,所以我从基础开始;假设一个对象实现了实现复制和赋值的传统方式:
现在输入右值并移动语义。据我所知,这将是一个有效的实现:
但是编译器(VC++ 2010 SP1)对此不太满意,编译器通常是正确的:
q3:如何解决?回到 AnObject& operator = ( const AnObject& rh ) 肯定会修复它,但我们不会失去一个相当重要的优化机会吗?
除此之外,很明显移动构造函数和赋值的代码充满了重复。所以现在我们忘记了歧义并尝试使用复制和交换来解决这个问题,但现在是右值。正如这里所解释的,我们甚至不需要自定义交换,而是让 std::swap 完成所有工作,这听起来很有希望。所以我写了以下内容,希望 std::swap 会使用 move 构造函数复制构造一个临时的,然后用 *this 交换它:
但这不起作用,而是由于无限递归而导致堆栈溢出,因为 std::swap 再次调用我们的 operator = ( AnObject&& rh )。q4:有人可以提供一个示例来说明示例中的含义吗?
我们可以通过提供第二个交换函数来解决这个问题:
现在有几乎两倍的金额代码,但是它的移动部分通过允许相当便宜的移动来支付;但另一方面,正常的分配不能再从复制省略中受益。在这一点上,我真的很困惑,再也看不到什么是对和错了,所以我希望在这里得到一些意见..
更新所以似乎有两个阵营:
- 一种说法是跳过移动赋值运算符并继续执行 C++03 教给我们的操作,即编写一个按值传递参数的单个赋值运算符。
- 另一种说法是实现移动赋值运算符(毕竟现在是 C++11)并让复制赋值运算符通过引用获取其参数。
(好的,第三个阵营告诉我使用向量,但这超出了这个假设类的范围。好吧,在现实生活中我会使用向量,并且还会有其他成员,但是由于移动构造函数/分配不会自动生成(还没有?)问题仍然存在)
不幸的是,我无法在现实世界的场景中测试这两种实现,因为这个项目刚刚开始,数据实际流动的方式尚不清楚。所以我简单地实现了它们,为分配等添加了计数器,并运行了几次迭代。此代码,其中 T 是实现之一:
要么这段代码不够好,无法测试我所追求的,要么编译器太聪明了:不管我对 arraySize 和 numIter 使用什么,两个阵营的结果几乎相同:分配的数量相同,时间上的微小变化,但没有可重现的显着差异。
因此,除非有人能指出更好的测试方法(鉴于实际使用场景尚不清楚),否则我将不得不得出结论,这无关紧要,因此留给开发人员的口味。在这种情况下,我会选择#2。
c++ - 重载 R 值引用和代码重复
考虑以下:
感谢 r-value 引用,通过这四个 operator+ 重载,我可以通过重用临时对象来最小化创建的对象数量。但我不喜欢这里引入的重复代码。我可以用更少的重复来达到同样的效果吗?
c++ - 按值返回时,值参数是否隐式移动?
考虑以下函数:
会return x
调用复制构造函数还是移动构造函数?(让我们把 NRVO 放在一边。)
为了调查,我写了一个简单的Foo
类,它只能移动但不能复制:
如果在按值返回值参数时调用了移动构造函数,一切都应该没问题。但是当前的 g++ 编译器抱怨return x
以下错误消息:
如果我替换return x
为return std::move(x)
,一切都很好。由此我得出结论,如果需要,必须明确地从值参数移动。g++ 的行为是否符合要求?
c++ - 最后一次使用可移动对象时,编译器会自动使用移动语义吗?
我最近一直在研究右值引用并得出一个结论,即在将制作对象的完整副本的任何地方都使用按值传递是非常有利的(有关完整的理由,请参见例如如何在添加右值引用运算符时减少冗余代码重载?和想要速度?按值传递!),因为编译器可以在诸如f(std::move(a));
, where f
is defined as的情况下自动优化一个副本void f(A a);
。
pass-by-value-everywhere 的一个负面后果是,std::move
即使在简单的情况下,所有代码也会变得乱七八糟,例如:
显然,如果我只写以下内容:
即使没有提示也不应该用额外的副本惩罚我,编译器应该不难识别它a
接近其生命周期的尽头。事实上,即使在复杂的函数中,编译器也应该能够识别这一点。
问题:
C++0x 标准是否允许这种优化?
编译器是否使用它?即使在复杂的情况下,即功能由不止一行组成?
这种优化有多可靠,即我可以期望编译器像我期望编译器应用返回值优化一样多地利用它吗?
c++11 - 为什么在这个人为的示例中不调用移动构造函数?
来自 GetPerson 的未命名返回值不应该绑定到移动构造函数吗?
人.hpp
主文件
我正在使用 gcc 4.4.3 版(Ubuntu 4.4.3-4ubuntu5)并编译:
是 RVO 还是 NRVO 的原因?
c++ - 右值函数重载
我想重载一个函数,以便它以某种方式操纵其参数,然后返回对该参数的引用——但如果参数不可变,那么它应该返回参数的操纵副本。在搞砸了很久之后,这就是我想出的。
这段代码似乎工作正常,但我很想知道是否有人能想出更好的方法来做到这一点。
这是一个测试程序:
正确的输出是
我想如果我能做到这一点会稍微整洁一些:
当然,这是行不通的,因为大多数函数调用foo
都是模棱两可的——包括调用foo
本身!但是如果我能以某种方式告诉编译器优先考虑第一个......
正如我所说,我发布的代码可以正常工作。我不喜欢的主要是重复的额外代码。如果我有一堆这样的函数,它会变得一团糟,而且大部分都是非常重复的。所以作为我问题的第二部分:任何人都可以想出一种方法来自动生成第二个和第三个foo
函数的代码吗?例如
c++ - 移动操作的条件编译
如何检查我的编译器是否支持右值引用?是否有标准的预处理器宏,或者不同的编译器有不同的宏?理想情况下,我想这样写: