前段时间我已经问过一个类似的问题,但我仍然不清楚一些细节。
什么情况下调用postblit构造函数?
移动对象的语义是什么?它会被postblitted和/或破坏吗?
如果我按值返回局部变量会发生什么?它会被隐式移动吗?
如何将表达式转换为右值?例如,通用交换会是什么样子?
前段时间我已经问过一个类似的问题,但我仍然不清楚一些细节。
什么情况下调用postblit构造函数?
移动对象的语义是什么?它会被postblitted和/或破坏吗?
如果我按值返回局部变量会发生什么?它会被隐式移动吗?
如何将表达式转换为右值?例如,通用交换会是什么样子?
每当复制结构时都会调用 postblit 构造函数 - 例如,将结构传递给函数时。
移动是按位复制。postblit 构造函数永远不会被调用。析构函数永远不会被调用。这些位被简单地复制。原件已“移动”,因此无需创建或销毁任何内容。
它会被移动。这是移动的主要例子。
swap
如果您想让函数尽可能高效,则函数必须考虑许多不同的情况。我建议只使用std.algorithm 中的交换函数。经典的交换会导致复制,因此会调用 postblit 构造函数和析构函数。移动通常由编译器完成,而不是程序员。然而,看看 的官方实现,swap
它似乎在使用一些技巧来尽可能地将移动语义从交易中移除。无论如何,移动通常由编译器完成。它们是一种优化,它会在它知道它可以做的地方做(RVO是它可以做的经典案例)。
根据TDPL (p. 251),只有 2 种情况 D保证会发生移动:
- 所有匿名右值都被移动,而不是复制。
this(this
当源是匿名右值(即,上述函数中的临时值)时,永远不会插入对 ) 的调用hun
。- 所有在函数内部堆栈分配并返回的命名临时对象都省略了对
this(this)
.- 不能保证观察到其他潜在的省略。
因此,编译器可能会在其他地方使用移动,但不能保证它会。
据我所理解:
1) 当一个结构被复制时,而不是移动或构造。
2)移动语义的要点是两者都不需要发生。结构的新位置使用结构的按位副本进行初始化,旧位置超出范围并变得不可访问。因此,该结构已从 A“移动”到 B。
3)这是典型的移动情况:
S init(bool someFlag)
{
S s;
s.foo = someFlag? bar : baz;
return s; // `s` can now be safely moved from here...
}
// call-site:
S s = init(flag);
//^ ... to here.