Why is the copy constructor called 25 times, and the insert loop repeats only 10 times?

I am wondering why in the following C ++ code, the copy constructor is called 25 times for 10 iterations?

If it was 10, then OK 10/10 = 1, or 20/10 = 2, or 30/10 = 3, but 25/10 = 2.5? What does .5it mean here?

Title:

class Person
{
public:
    Person(std::string name, int age);
    Person(const Person &person);

    const std::string &getName() const;
    int getAge() const;

private:
    std::string name;
    int age;
};

Source:

Person::Person(string name, int age) : name(std::move(name)), age(age)
{}

Person::Person(const Person &person)
{
    this->name = person.name;
    this->age = person.age;
    static int count = 0;
    count++;
    cout << ">>Copy-Person::Person(Person &person) " << count << endl;
}

const string &Person::getName() const
{
    return name;
}

int Person::getAge() const
{
    return age;
}

Application:

int main()
{
    vector<Person> persons;

    for (int i = 0; i < 10; ++i)
    {
        Person person(to_string(i + 1), i);
        persons.push_back(person);
    }
    cout << "-----------------------------------------------" << endl;
    for (Person &person : persons)
    {
        cout << "name = " << person.getName() << " age = " << person.getAge() << endl;
    }
    return 0;
}

Output:

>>Copy-Person::Person(Person &person) 1
>>Copy-Person::Person(Person &person) 2
>>Copy-Person::Person(Person &person) 3
>>Copy-Person::Person(Person &person) 4
>>Copy-Person::Person(Person &person) 5
>>Copy-Person::Person(Person &person) 6
>>Copy-Person::Person(Person &person) 7
>>Copy-Person::Person(Person &person) 8
>>Copy-Person::Person(Person &person) 9
>>Copy-Person::Person(Person &person) 10
>>Copy-Person::Person(Person &person) 11
>>Copy-Person::Person(Person &person) 12
>>Copy-Person::Person(Person &person) 13
>>Copy-Person::Person(Person &person) 14
>>Copy-Person::Person(Person &person) 15
>>Copy-Person::Person(Person &person) 16
>>Copy-Person::Person(Person &person) 17
>>Copy-Person::Person(Person &person) 18
>>Copy-Person::Person(Person &person) 19
>>Copy-Person::Person(Person &person) 20
>>Copy-Person::Person(Person &person) 21
>>Copy-Person::Person(Person &person) 22
>>Copy-Person::Person(Person &person) 23
>>Copy-Person::Person(Person &person) 24
>>Copy-Person::Person(Person &person) 25
-----------------------------------------------
name = 1 age = 0
name = 2 age = 1
name = 3 age = 2
name = 4 age = 3
name = 5 age = 4
name = 6 age = 5
name = 7 age = 6
name = 8 age = 7
name = 9 age = 8
name = 10 age = 9
+6
source share
3 answers

You do not reserve memory for your vector persons. This means that when persons.size() == persons.capacity()over push_back, the vector will allocate a new large buffer on the heap and copy each element into it. This is why you see more copies than expected.

If you write ...

persons.reserve(10); 

... .

wandbox


, std::vector::emplace_back, std::vector::reserve:

for (int i = 0; i < 10; ++i)
{
    persons.emplace_back(to_string(i + 1), i);
}

:

name = 1 age = 0

name = 2 age = 1

name = 3 age = 2

name = 4 age = 3

name = 5 age = 4

name = 6 age = 5

name = 7 age = 6

name = 8 age = 7

name = 9 age = 8

name = 10 age = 9

wandbox

+4

size() > capacity() vector, . , . , , , , , , .

#iterator current size  capacity  times of the copy (for reallocatioin + for push_back)
1         0             0         0 + 1             
2         1             1         1 + 1             
3         2             2         2 + 1             
4         3             4         0 + 1             
5         4             4         4 + 1             
6         5             8         0 + 1             
7         6             8         0 + 1             
8         7             8         0 + 1             
9         8             8         8 + 1             
10        9             16        0 + 1             

25 .

@VittorioRomeo, std::vector:: reserve, .

+2

std::vector::size() std::vector::capacity(), std::vector , , .
Person ( VS2015, 35 ).

, std::vector reserve(), 10 :

vector<Person> persons;

// Reserve room in the vector to store 10 persons
persons.reserve(10);

for (int i = 0; i < 10; ++i)
{
    Person person(to_string(i + 1), i);
    persons.push_back(person);
}

, , ( ).

All that said, if your Personclass moves constructively , it std::vectorwill move previously created objects Personinstead of copying them, which is faster.

If you add this line to your class Person:

class Person 
{
  public:
   ...

   // Synthesize default move constructor
   Person(Person&&) = default;
   ...
};

you get exactly 10 calls to the copy constructor, even if you do not call the method vector::reserve().

+2
source

All Articles