我有一个Class Child,并且有一个简单的 vector 推回实现,如下所示:

#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);
}

v.push_back( Item1 );被调用之后,我有以下输出:
Constructing Child
Copy-Constructing Child
Copy-Constructing Child
Destructing Child

我期望Copy-Constructing Child仅出现一次。为什么复制构造函数被调用两次?

最佳答案

官方答案:对于您的类(class),std::vector可自由制作任意数量的副本,因为标准中没有指定限制。

可能正在发生的事情:在将对象作为参数传递时以及在对 vector 进行内部调整大小时再次进行复制。

这不是效率低下吗?是

我该如何改善?

删除自定义析构函数和复制构造函数,或者定义自定义移动构造函数和复制运算符。前者允许编译器创建自己的移动操作,后者提供它们。

一旦编译器可以推断出您的类是可移动的,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

关于c++ - 为什么在执行 vector 时会两次调用复制构造函数.push_back,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30358475/

10-11 22:55
查看更多