Questions about postblit and move semantics

2019-02-06 04:06发布

I have already asked a similar question a while ago, but I'm still unclear on some details.

  1. Under what circumstances is the postblit constructor called?

  2. What are the semantics of moving an object? Will it be postblitted and/or destructed?

  3. What happens if I return a local variable by value? Will it implicitly be moved?

  4. How do I cast an expression to an rvalue? For example, how would a generic swap look like?

2条回答
何必那么认真
2楼-- · 2019-02-06 04:30
  1. A postblit constructor is called whenever the struct is copied - e.g. when passing a struct to a function.

  2. A move is a bitwise copy. The postblit constructor is never called. The destructor is never called. The bits are simply copied. The original was "moved" and so nothing needs to be created or destroyed.

  3. It will be moved. This is the prime example of a move.

  4. There are a number of different situations that a swap function would have to worry about if you want to make it as efficient as possible. I would advise simply using the swap function in std.algorithm. The classic swap would result in copying and would thus call the postblit constructor and the destructor. Moves are generally done by the compiler, not the programmer. However, looking at the official implementation of swap, it looks like it plays some tricks to get move semantics out of the deal where it can. Regardless, moves are generally done by the compiler. They're an optimization that it will do where it knows that it can (RVO being the classic case where it can).

According to TDPL (p. 251), there are only 2 cases where D guarantees that a move will take place:

  • All anonymous rvalues are moved, not copied. A call to this(this) is never inserted when the source is an anonymous rvalue (i.e., a temporary as featured in the function hun above).
  • All named temporaries that are stack-allocated inside a function and then returned elide a call to this(this).
  • There is no guarantee that other potential elisions are observed.

So, the compiler may use moves elsewhere, but there's no guarantee that it will.

查看更多
疯言疯语
3楼-- · 2019-02-06 04:40

As far as I understand:

1) When a struct is copied, as opposed to moved or constructed.

2) The point of move semantics is that neither of the two needs to happen. The new location of the struct is initialized with a bit-wise copy of the struct, and the old location goes out of scope and becomes inaccessible. Thus, the struct has "moved" from A to B.

3) That is the typical move situation:

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.
查看更多
登录 后发表回答