2

I am trying to understand why do I get an extra move constructor operation when adding my resource management objects to vector.

Here is my resource management class:

class Resource
{
public:
    Resource() {
        own_ = true;
        id_ = next_id++;
        std::cout << "Resource " << id_ << " constructed\n";
    }

    Resource(Resource&& c) {
        std::cout << "Move constructed from " << c.id_ << " to " << id_ << "\n";
        swap(*this, c);
    }

    ~Resource() {
        if (own_) {
            std::cout << "Resource " << id_ << " destructed\n";
        }
    }

    Resource&  operator=(Resource&& c) {
        std::cout << "Move assigned from " << c.id_ << " to " << id_ << "\n";
        swap(*this, c);
        return *this;
    }

    void swap(Resource& a, Resource& b) {
        std::swap(a.id_, b.id_);
        std::swap(a.own_, b.own_);
    }

    Resource(Resource const&) = delete;
    auto operator=(Resource const&)->Resource = delete;
    static int next_id;
private:
    bool own_ = false;
    int id_;
};
int Resource::next_id = 1;  

And here is the main function where I am creating two objects and moving them to my vector of resources:

int main() {
    std::vector<Resource> resources;

    Resource a, b;
    resources.push_back(std::move(a));
    resources.push_back(std::move(b));

    return 0;
}

And here is the output. First 4 lines are like I expected them to be, but last line seems to be extra operation like something is being rearranged or sorted inside a vector. Final contents of the vector are as expected though - 2 resource objects but my output is:

Resource 1 constructed  
Resource 2 constructed  
Move constructed from 1 to -842150451  
Move constructed from 2 to -842150451  
Move constructed from 1 to -842150451
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • http://stackoverflow.com/questions/23717151/why-emplace-back-is-faster-than-push-back – greedy52 Feb 10 '17 at 19:43
  • Note that if your copy constructor wasn't `delete`d, you'd have only seen 2 move constructions, but for a [very different reason](http://stackoverflow.com/q/8001823/241631). – Praetorian Feb 10 '17 at 19:53
  • My last comment should've said if your copy constructor was `default`ed (since it's implicitly deleted anyway). – Praetorian Feb 10 '17 at 20:11

1 Answers1

4

You see the additional move constructor call because the vector grew. So the first move the is first time you insert into the vector and the extraneous move is from moving that element to the new buffer that was create to fit the next element into vector.

Generally when you have a empty vector push_pack will allocate a 1 space storage and add the element into it. Then the next time you call push_back it will allocate new storage with double the capacity and move/copy everything from the old storage to the new storage. Every time you call push_back if the size() == capacity() then the vector needs to allocate new storage and move everything to that new storage and then add the new element.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402