The efficient way to write move copy and move assignment constructors

前端 未结 3 1751
长情又很酷
长情又很酷 2021-01-05 23:57

Are the following assignment and copy move constructors the most efficient? if anybody have other way please tell me? I mean what bout std::swap? and calling assignment th

3条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2021-01-06 00:24

    The answer is in response to @Abdulrhman's complaint in the comments above that things fail for some (obscure) sequences of assignments. Put into a seperate answer because it's more readable that way.

    The complaint was that

    Widget w(2);
    w = Widget(1) = std::move(w);
    

    crashes. Here's the output I get from

    Widget w(2);
    w.data()[0] = 0xDEAD; w.data()[1] = 0xBEEF;
    w = Widget(1) = std::move(w);
    std::cerr << std::hex << w.data()[0] << w.data()[1] << std::endl;
    

    with some code added to Widget to log constructor, destructor and assignment operator calls. Interleaves are comments about where those calls come from

    w is constructed
    0x7fff619c36c0: [constructor] allocated 2@0x1043dff80
    temporary Widget(1) is constructed
    0x7fff619c37c0: [constructor] allocated 1@0x1043e0180
    first (right) assignment operator argument is constructed. w is empty afterwards!
    0x7fff619c3800: [default constructor] empty
    0x7fff619c3800: [move constructor] stealing 2@0x1043dff80 from 0x7fff619c36c0, replacing with 0@0x0
    first assignment operator does it's job, i.e. moves from by-value argument.
    0x7fff619c37c0: [assignment] stealing 2@0x1043dff80 from 0x7fff619c3800, replacing with 1@0x1043e0180
    second (left) assignment operator arguments is constructed
    0x7fff619c3780: [constructor] allocated 2@0x1043e0280
    0x7fff619c3780: [copy constructor] copying 2@0x1043dff80 from 0x7fff619c37c0
    second assignment operator does it's job, i.e. moves from by-value argument
    0x7fff619c36c0: [assignment] stealing 2@0x1043e0280 from 0x7fff619c3780, replacing with 0@0x0
    second assingment operator's by-value argument is destructed
    0x7fff619c3780: [destructor] deleting 0@0x0
    first assignment operator's by-value argument is destructed
    0x7fff619c3800: [destructor] deleting 1@0x1043e0180
    temporary created as Widget(1) is destructed.
    0x7fff619c37c0: [destructor] deleting 2@0x1043dff80
    data contains in "w" after assignments.
    deadbeef
    finally, "w" is destructed.
    0x7fff619c36c0: [destructor] deleting 2@0x1043e0280
    

    I can see no problem there, and compiling this with clang and -faddress-sanitizer, -fcatch-undefined-behaviour doesn't complain either.

    Note, though, that the second assigment (the left = operator) copies instead of moving. This is because the first (right) assignment operator returns an lvalue-reference.

提交回复
热议问题