问题标签 [move-semantics]

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.

0 投票
2 回答
1243 浏览

c++ - 为什么这个右值调用模棱两可?

为什么这个右值调用模棱两可?我可以拥有 AA 和 AA& 并且编译器会知道使用AA&. 但是当我添加第三个选项时,我得到了一个错误。显然 AA&& 是一个更好的重载,然后其他像 int 的 int 比 long 更好。为什么这是模棱两可的?有没有办法可以保留所有 3 个重载并明确我想要哪个?(类型转换(AA&&)不会这样做)。

0 投票
2 回答
11445 浏览

c++ - 对类中的方法正确使用 `= delete`

对于取消定义类的所有其他生成的方法和构造函数,以下片段是否正确?

这会删除每个默认编译器实现,只留下析构函数,对吗?如果没有它,我猜这个类将(几乎)无法使用,但我也可以删除它,对吗?

Picture&move-assign的返回类型operator=(Picture&&)是否正确?如果我Picture&&为返回类型写会有所不同吗?

0 投票
5 回答
15716 浏览

c++ - 在任何情况下,返回 RValue 引用 (&&) 是有用的吗?

函数应该返回 RValue 引用是否有原因?一种技术、技巧、习语或模式?

我知道一般返回引用的危险,但有时我们还是会这样做,不是吗?T& T::operator=(T)只是一个惯用的例子。但是怎么样T&& func(...)?是否有任何一般的地方可以让我们从中受益?与仅编写客户端代码相比,编写库或 API 代码时可能有所不同?

0 投票
1 回答
10340 浏览

c++ - 将 unique_ptrs 从一个向量移动到另一个向量

我想将存储在它们的未排序向量中的 unique_ptr 移动到另一个向量,该向量将包含指针的排序向量。

确定移动 unique_ptr 不会自动删除第一个向量中的元素吗?我怎样才能做到这一点?

我想做的例子:

我希望意图是明确的。

更新我的算法不允许就地排序。如果今天有人感觉很好(我不是在问,我的问题见上文),请随时针对这种情况实施它并向我展示。我真的需要“按动作排序”。而且我真的不明白为什么搬家会得多。

0 投票
6 回答
6782 浏览

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。

0 投票
2 回答
587 浏览

c++ - 按值返回时,值参数是否隐式移动?

考虑以下函数:

return x调用复制构造函数还是移动构造函数?(让我们把 NRVO 放在一边。)

为了调查,我写了一个简单的Foo类,它只能移动但不能复制:

如果在按值返回值参数时调用了移动构造函数,一切都应该没问题。但是当前的 g++ 编译器抱怨return x以下错误消息:

如果我替换return xreturn std::move(x),一切都很好。由此我得出结论,如果需要,必须明确地从值参数移动。g++ 的行为是否符合要求?

0 投票
1 回答
2263 浏览

c++ - 最后一次使用可移动对象时,编译器会自动使用移动语义吗?

我最近一直在研究右值引用并得出一个结论,即在将制作对象的完整副本的任何地方都使用按值传递是非常有利的(有关完整的理由,请参见例如如何在添加右值引用运算符时减少冗余代码重载?想要速度?按值传递!),因为编译器可以在诸如f(std::move(a));, where fis defined as的情况下自动优化一个副本void f(A a);

pass-by-value-everywhere 的一个负面后果是,std::move即使在简单的情况下,所有代码也会变得乱七八糟,例如:

显然,如果我只写以下内容:

即使没有提示也不应该用额外的副本惩罚我,编译器应该不难识别它a接近其生命周期的尽头。事实上,即使在复杂的函数中,编译器也应该能够识别这一点。

问题:

  1. C++0x 标准是否允许这种优化?

  2. 编译器是否使用它?即使在复杂的情况下,即功能由不止一行组成?

  3. 这种优化有多可靠,即我可以期望编译器像我期望编译器应用返回值优化一样多地利用它吗?

0 投票
4 回答
638 浏览

c++ - qsort 在 C++ 中不适用于哪些类型?

std::sort通过 using 交换元素std::swap,后者又使用复制构造函数和赋值运算符,确保在交换值时获得正确的语义。

qsort通过简单地交换元素的底层位来交换元素,忽略与您正在交换的类型相关的任何语义。

即使qsort不知道要排序的类型的语义,它仍然可以很好地处理非平凡的类型。如果我没记错的话,它适用于所有标准容器,尽管它们不是 POD 类型。

我认为qsort在一个类型上正确工作T的先决条件T是 /trivially 可移动 /。在我的脑海中,唯一不能轻易移动的类型是那些具有内部指针的类型。例如:

如果你对一个数组进行排序,NotTriviallyMovable那么m_someElements 最终会指向错误的元素。

我的问题是:还有哪些其他类型不适用qsort

0 投票
3 回答
20211 浏览

c++ - 从 C++11 中的函数调用返回 std::vector 的正确方法(移动语义)

我想填充 std::vector (或其他一些 STL 容器):

1.好看的ctor,昂贵的性能

2.更好的性能,更差的ctor

get_vector是否可以使用 C++0x(移动语义功能等)重写第一个示例中的函数以避免冗余复制和构造函数调用?

0 投票
1 回答
23071 浏览

c++ - 移动或命名返回值优化 (NRVO)?

假设我们有以下代码:

似乎编译器在这里有两种方法:

(a) NRVO:破坏 x,然后构造 f() 代替 x。
(b) 移动:在临时空间中构造 f(),将 f() 移动到 x 中,破坏 f()。

根据标准,编译器是否可以自由使用任何一种方法?