Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Questions about postblit and move semantics

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?

like image 947
fredoverflow Avatar asked Jul 30 '11 18:07

fredoverflow


2 Answers

  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.

like image 193
Jonathan M Davis Avatar answered Nov 14 '22 11:11

Jonathan M Davis


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.
like image 33
jA_cOp Avatar answered Nov 14 '22 13:11

jA_cOp