The efficient way to write move copy and move assignment constructors

前端 未结 3 1725
长情又很酷
长情又很酷 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:31

    Looks fine from an efficiency POV, but contains an awful lot of duplicated code. I'd

    • Implement a swap() operator for your class.
    • Initialize length_ and data_ where they are declared.
    • Implement operations in terms of other operations whereever possible.

    You might want to use std::memcpy instead of std::copy since you're dealing with a raw array anyway. Some compilers will do that for you, but probably not all of them...

    Here's a de-duplicated version of your code. Note how there is only one place which needs to know how two instances of Widget are swapped. And only one place which knows how to allocate a Widget of a given size.

    Edit: You usually also want to use argument-dependent lookup to locate swap, just in case you ever have non-primitive members.

    Edit: Integrated @Philipp's suggestion of making the assignment operator take it's argument by value. That way, it acts as both move assignment and copy assignment operator. In the move case, not that if you pass a temporary, it won't be copied, since the move constructor, not the copy constructor will be used to pass the argument.

    Edit: C++11 allows non-cost members to be called on rvalues for compatibility with previous versions of the standard. This allows weird code like Widget(...) = someWidget to compile. Making operator= require an lvalue for this by putting & after the declaration prevents that. Note though that the code is correct even without that restriction, but it nevertheless seems like a good idea, so I added it.

    Edit: As Guillaume Papin pointed out, the destructor should use delete[] instead of plain delete. The C++ standard mandates that memory allocated via new [] be deleted via delete [], i.e. it allows new' andnew []` to use different heaps.

    class Widget
    {
    public:
        Widget(int length)
            :length_(length)
            ,data_(new int[length])
        {}
    
        ~Widget()
        {
            delete[] data_;
        }
    
        Widget(const Widget& other)
            :Widget(other.length_)
        {
            std::copy(other.data_, other.data_ + length_, data_);
        }
    
        Widget(Widget&& other)
        {
            swap(*this, other);
        }
    
        Widget& operator= (Widget other) &
        {
            swap(*this, other);
            return *this;
        }
    
        int length() const
        {
            return length_;
        }
    
    private:
        friend void swap(Widget& a, Widget& b);
    
        int length_ = 0;
        int* data_ = nullptr;
    };
    
    void swap(Widget& a, Widget& b) {
        using std::swap;
        swap(a.length_, b.length_);
        swap(a.data_, b.data_);
    }
    

提交回复
热议问题