【问题标题】:Questions about postblit and move semantics关于 postblit 和 move 语义的问题
【发布时间】:2011-10-16 15:11:27
【问题描述】:

前段时间我已经问过a similar question,但有些细节我还不清楚。

  1. 什么情况下调用postblit构造函数?

  2. 移动对象的语义是什么?它会被后期处理和/或破坏吗?

  3. 如果我按值返回局部变量会发生什么?会隐式移动吗?

  4. 如何将表达式转换为右值?例如,通用交换会是什么样子?

【问题讨论】:

  • 通用交换:void swap(T)(ref T t1,ref T t2){T tmp=t1;t1=t2;t2=tmp;}
  • @ratched:你在那里有三个复制操作。我想要移动操作。
  • 那么你需要转换为字节数组检查github.com/D-Programming-Language/phobos/blob/master/std/… 的火卫一实现
  • @ratchet 怪胎:您可以像在通常的帖子中一样在 cmets 中使用 markdown 链接,即 [string](url)。详情here
  • @AlexanderMalakhov 自从我在 7 月 发布后我就明白了

标签: templates return-value d copy-constructor move-semantics


【解决方案1】:
  1. 每当复制结构时都会调用 postblit 构造函数 - 例如将结构传递给函数时。

  2. 移动是按位复制。 postblit 构造函数永远不会被调用。析构函数永远不会被调用。这些位被简单地复制。原件已“移动”,因此无需创建或销毁任何内容。

  3. 它将被移动。这是移动的主要例子。

  4. 如果您想让swap 函数尽可能高效,则必须考虑许多不同的情况。我建议只使用swap function in std.algorithm。经典的交换会导致复制,因此会调用 postblit 构造函数和析构函数。移动通常由编译器完成,而不是程序员。然而,looking at the official implementationswap,看起来它玩了一些技巧来尽可能地将移动语义从交易中移除。无论如何,移动通常由编译器完成。它们是一种优化,它会在它知道它可以做的地方做(RVO 是它可以做的经典案例)。

根据TDPL (p. 251),只有 2 种情况 D 保证会发生移动:

  • 所有匿名右值都被移动,而不是复制。致电this(this) 当源是匿名右值(即 临时功能,如上面的函数 hun 中所示)。
  • 在函数内部堆栈分配的所有命名临时对象和 然后回了一个电话给this(this)
  • 不能保证观察到其他潜在的省略。

因此,编译器可能会在其他地方使用移动,但不能保证它会。

【讨论】:

  • std.algoritm 链接对我来说已经失效了。
  • 我不知道为什么。它对我来说很好用。这只是 github 上 std.algorithm 的链接。
  • @BCS:啊,所以你需要更深入。
  • 我对其进行了调整,以便第一个链接现在指向 swap 的 Phobos 文档,稍后链接到实际实现,所以如果有人对 github 的链接有任何问题,它会现在是“查看官方实施”链接。不过,我的链接没有问题。可能是浏览器问题。
【解决方案2】:

据我所知:

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.

【讨论】:

  • 只是澄清一下,当“旧位置超出范围”时,它不会被破坏,对吧?
  • 完全正确 - 它也不是在调用站点构建或后期处理的,它只是继续存在。
猜你喜欢
  • 1970-01-01
  • 2013-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-25
  • 1970-01-01
  • 1970-01-01
  • 2011-07-28
相关资源
最近更新 更多