How to copy (or swap) objects of a type that contains members that are references or const?

前端 未结 5 2065
生来不讨喜
生来不讨喜 2020-12-15 10:08

The problem I am trying to address arises with making containers such as an std::vector of objects that contain reference and const data members:



        
5条回答
  •  温柔的废话
    2020-12-15 10:25

    If you implement this with move operators there is a way:

    Bar & Bar :: operator = (Bar && source) {
        this -> ~ Bar ();
        new (this) Bar (std :: move (source));
        return *this;
    }
    

    You shouldn't really use this trick with copy constructors because they can often throw and then this isn't safe. Move constructors should never ever throw, so this should be OK.

    std::vector and other containers now exploit move operations wherever possible, so resize and sort and so on will be OK.

    This approach will let you keep const and reference members but you still can't copy the object. To do that, you would have to use non-const and pointer members.

    And by the way, you should never use memcpy like that for non-POD types.

    Edit

    A response to the Undefined Behaviour complaint.

    The problem case seems to be

    struct X {
        const int & member;
        X & operator = (X &&) { ... as above ... }
        ...
    };
    
    X x;
    const int & foo = x.member;
    X = std :: move (some_other_X);
    // foo is no longer valid
    

    True it is undefined behaviour if you continue to use foo. To me this is the same as

    X * x = new X ();
    const int & foo = x.member;
    delete x;
    

    in which it is quite clear that using foo is invalid.

    Perhaps a naive read of the X::operator=(X&&) would lead you to think that perhaps foo is still valid after a move, a bit like this

    const int & (X::*ptr) = &X::member;
    X x;
    // x.*ptr is x.member
    X = std :: move (some_other_X);
    // x.*ptr is STILL x.member
    

    The member pointer ptr survives the move of x but foo does not.

提交回复
热议问题