Why copy-constructor is called twice when executing vector.push_back

I have a child class and a simple implementation of vector output back:

#include <stdio.h>
#include <vector>
#include <iostream>

class Child 
{
    public:
        Child();
        Child(const Child &item);
        ~Child();
};

Child::Child()
{
    std::cout<<"Constructing Child\n";
}

Child::Child(const Child &item)
{
    std::cout<<"Copy-Constructing Child\n";
}

Child::~Child()
{
    std::cout<<"Destructing Child\n";
}

int main()
{
    std::vector<Child> v;
    Child Item1;
    v.push_back(Item1);
}

Immediately after the call v.push_back( Item1 );, I have the following outputs:

Constructing Child
Copy-Constructing Child
Copy-Constructing Child
Destructing Child

I expected to Copy-Constructing Childappear only once. Why is the constructor copy created twice?

+2
source share
2 answers

The official answer. In the case of your std :: vector class, you can make as many copies as they like, since there are no restrictions in the standard.

What probably happens: a copy is executed when the object is passed as a parameter and again when the vector changes inside.

Is it inefficient? Yes

How to improve it?

, . , .

, , , std::vector , ( , Child, Item1)

:

#include <stdio.h>
#include <vector>
#include <iostream>

class Child
{
public:
    Child();
    Child(const Child &item);
    Child(Child&& item);
    Child& operator=(const Child &item);
    Child& operator=(Child&& item);
    ~Child();

private:
    std::string name() const {
        return std::string { _zombie ? "zombie" : "child" };
    }
    bool _zombie = false;
};

Child::Child()
{
    std::cout << "constructing " << name() << "\n";
}

Child::Child(const Child &item)
{
    std::cout << "copy-constructing " << name() << "\n";
}

Child::Child(Child &&item)
{
    std::cout << "move-constructing " << name() << "\n";
    item._zombie = true;
}

Child& Child::operator=(const Child &item)
{
    _zombie = false;
    std::cout << "assigning " << name() << "\n";
    return *this;
}

Child& Child::operator=(Child &&item)
{
    item._zombie = true;
    _zombie = false;
    std::cout << "move-assigning " << name() << "\n";
    return *this;
}

Child::~Child()
{
    std::cout << "destructing " << name() << "\n";
}

using namespace std;

int main(int argc, const char * argv[])
{
    {
        std::vector<Child> v;
        Child item1;
        v.push_back(item1);
    }
    cout << endl;

    {
        std::vector<Child> v;
        v.push_back(Child{});
    }
    cout << endl;

    {
        std::vector<Child> v;
        Child item1;
        v.push_back(std::move(item1));
    }
    cout << endl;
    return 0;
}

:

constructing child
copy-constructing child
destructing child
destructing child

constructing child
move-constructing child
destructing zombie
destructing child

constructing child
move-constructing child
destructing zombie
destructing child
+1

, . , .:-( Microsoft. , , , , . , , , , .

+1

All Articles