关于postblit和移动语义的问题

时间:2011-07-30 18:03:05

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

我刚才已经问过a similar question,但我仍然不清楚某些细节。

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

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

  3. 如果按值返回局部变量会怎样?它是否会被隐含地移动?

  4. 如何将表达式转换为右值?例如,通用交换的外观如何?

2 个答案:

答案 0 :(得分:16)

  1. 每当复制结构时都会调用postblit构造函数 - 例如将结构传递给函数时。

  2. 移动是按位复制。永远不会调用postblit构造函数。析构函数永远不会被调用。这些位只是复制。原件被“移动”,因此不需要创建或销毁任何东西。

  3. 它会被移动。这是此举的主要例子。

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

  5. 根据RVO(第251页),只有2例D 保证移动将会发生:

      
        
    • 移动所有匿名rvalues,而不是复制。致电this(this)   当源是匿名右值时(即,a。),它永远不会被插入   临时的,如上面函数hun中所述。)
    •   
    • 在函数内部堆栈分配的所有命名临时对象   然后给elide打电话this(this)
    •   
    • 无法保证可以观察到其他潜在的分歧。
    •   

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

答案 1 :(得分:4)

据我所知:

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.