2

i just wrote a code for move constructor its being called again for value 2 passed into the pushback method

#include <iostream>
#include <vector>
using namespace std;
class n{
    int *ptr;
    public:
    n(int d):ptr{new int(d)}{cout<<"constuctor called for "<<d<<endl;
    }
    n(n &&s)noexcept:ptr{s.ptr}{
        s.ptr=nullptr;
        cout<<"move constructor called for "<<*ptr<<endl;}//this is being called again for 2

    ~n(){
        if(ptr==nullptr)
        cout<<"freeing storage for nullptr "<<ptr<<endl;
        else
        cout<<"freeing storage for ptr "<<*ptr<<endl;
        delete ptr;
    }
};
 int main() {
    vector<n>b;
    b.push_back(n{2});
    b.push_back(n{3});;
    return 0;
}
Tony Star
  • 21
  • 1
  • Check `capacity` of `vector`... – Jarod42 May 17 '21 at 08:44
  • 1
    `std::vector` works by *reallocating* memory when needed, and then copying or moving the elements to the new memory. – Some programmer dude May 17 '21 at 08:45
  • Off-topic: Did you notice that `delete ptr` will be called for the null pointer, too, because of missing braces? That's not an error, actually, as deleting null pointers is legal, but unnecessary. – Aconcagua May 17 '21 at 08:48
  • 1
    To add to the comment by @Aconcagua, `ptr` will actually never be a null pointer, since plain `new` will throw an exception if it fails. – Some programmer dude May 17 '21 at 08:50
  • 1
    In succession to @Someprogrammerdude's comment: Try [`reserve`](https://en.cppreference.com/w/cpp/container/vector/reserve)-ing sufficient space for your objects. – Aconcagua May 17 '21 at 08:50

1 Answers1

2

A std::vector holds a buffer for its data that is automatically managed behind the scenes. Every time you add an item to the vector, this buffer is checked for its size - if it's exhausted, new memory will be allocated. Then all existing elements will be copied or moved (depending on the properties of the type in question) into the new buffer. To visualize this, take this empty buffer first.

||

Now, you call push_back on the vector. This requests space for one element. The capacity of the vector is empty (no buffer allocated yet), so it will allocate, and place the object into the buffer:

|-  n{2}  -|

Here, the capactiy is one - there is no space for additional elements. When you call push_back another time, the std::vector needs more buffer space. It does the following:

  • allocate dynamic memory
  • Move-construct all existing elements into the new buffer if they have noexcept move constructor - otherwise, they will be copied.
  • Append the new element.
old buffer:      |-  n{2}  -|
new buffer:      |-        -|-        -|
move existing:   |-  n{2}  -|-        -|
add new element: |-  n{2}  -|-   n{3} -|

When moving the existing elements into the new buffer, the second move construction happens.

lubgr
  • 37,368
  • 3
  • 66
  • 117