0

Below code outputs:

Default ctor is called
Copy ctor is called
Default ctor is called
Copy ctor is called
Copy ctor is called

Why for each push_back() the calling of copy constructor incremented by 1? I think it should only be called one time. Is there something which i miss here? please i need detailed explanation.

class A
{
public:
    A()
    {
        std::cout << "Default ctor is called" << std::endl;
    }
    A(const A& other)
    {
        if(this != &other)
        {
            std::cout << "Copy ctor is called" << std::endl;
            size_ = other.size_;
            delete []p;
            p = new int[5];
            std::copy(other.p, (other.p)+size_, p);
        }
    }
    int size_;
    int* p;
};
int main()
{
    std::vector<A> vec;
    A a;
    a.size_ = 5;
    a.p = new int[5] {1,2,3,4,5};
    vec.push_back(a);

    A b;
    b.size_ = 5;
    b.p = new int[5] {1,2,3,4,5};
    vec.push_back(b);

    return 0;
}
Islam Abdeen
  • 539
  • 3
  • 10
  • To push `class A` onto the vector it will need to create a copy of A. If this is undesirable you could use a smart pointer or simply pointers to NEW'd objects. – Richard Nixon Oct 24 '19 at 14:00
  • @RichardNixon Yes, i know. my question is about why copy constructor get called more than one time instead of just once. – Islam Abdeen Oct 24 '19 at 14:12
  • Ahh yes, sorry. Doing a little experimentation shows that the push_back() seems to create copies of everything *already* in the list (try adding a `c`). That's down to the internals of vector() I'm afraid. – Richard Nixon Oct 24 '19 at 14:41

1 Answers1

1

This is because the push_back in your example has to do a reallocation every time. If you reserve the size in advance then you see only one copy.

std::vector<A> vec;
vec.reserve(10);
Richard Nixon
  • 839
  • 6
  • 9
  • Yes you are right but that's a strange behavior. Do you know why `push_back` behave like that? Can't be implemented with `realloc` for example to use already existed memory if there is a space in heap? – Islam Abdeen Oct 24 '19 at 18:57
  • 1
    A `vector` can be accessed in a continuous way hence you can do `vec[n]` which you cannot do with a `std::list` for example. I don't know the inner workings of vector but I guess this is the safest way to add new entries when its internal space has been exhausted. – Richard Nixon Oct 24 '19 at 23:00