Questions about postblit and move semantics

前端 未结 2 1554
孤街浪徒
孤街浪徒 2020-12-31 06:38

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条回答
  • 2020-12-31 06:52
    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.

    0 讨论(0)
  • 2020-12-31 07:00

    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.
    
    0 讨论(0)
提交回复
热议问题