何时在cpp中调用复制构造函数?

时间:2016-07-03 12:39:18

标签: c++ vector capacity

#include<iostream>
#include<vector>
#include<list>
#include<queue>
#include<map>
using namespace std;
class dog{
    public:
        string name;
        dog();
        dog(const dog & d);
        void barkname(){
            cout<<"bark "<<name<<endl;
        }
        virtual ~dog(){
            //cout<<"delete dog "<<name<<endl;
        }
};

dog::dog(){
    cout<<"blank dog"<<endl;
    this->name="blank";
}

dog::dog(const dog &d){
    cout<<"copy dog"<< " "+d.name<<endl;
    string temp=d.name;
    this->name=temp+" copied";
}


int main(){
    dog d;
    d.name="d";
    dog dd;
    dd.name="dd";
    dog ddd;
    ddd.name="ddd";
    vector<dog> doglist;
    doglist.push_back(d);
    doglist.push_back(dd);
    doglist.push_back(ddd);
    return 0;
}

你好,我是cpp的新手。我试图在我的班级狗中使用复制构造函数。我使用push_back三次将三只狗推入载体。所以我期望复制构造函数被调用三次。但是,在执行代码之后,我发现复制构造函数被调用了六次,结果如下:

blank dog
blank dog
blank dog
copy dog d
copy dog dd
copy dog d copied
copy dog ddd
copy dog d copied copied
copy dog dd copied

我很困惑为什么狗被复制了很多次。我只执行了三次push_back。 谢谢。

感谢您指出类似的问题: why the copy-constructor is called twice when doing a vector.push_back

在这篇文章中,作者只有push_back一个对象,但复制构造函数被调用了两次。但是,在我的情况下,当我调用push_back一次时,复制构造函数只被调用一次。我已经明白我的问题所在,谢谢大家的帮助。

2 个答案:

答案 0 :(得分:17)

载体需要一些地方放置你的狗,所以它为它们分配内存。但它不能分配无限的内存。当您添加更多狗时,矢量需要分配更大的内存块,每次执行此操作时,它必须将您的狗重新安置到新家。与你目前设计的课程一样,这样做的唯一方法是复制它们,然后将原件放入睡眠状态。

如果你首先为所有狗保留了足够的空间(如下图所示),那么这不是必要的,你的狗可能已经开始了一个正确的滋扰,没有不断移动房子的分心。

doglist.reserve(3);

答案 1 :(得分:1)

如果要添加显示向量容量的语句,输出将更加清晰。例如

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class dog{
    public:
        string name;
        dog();
        dog(const dog & d);
        void barkname(){
            cout<<"bark "<<name<<endl;
        }
        virtual ~dog(){
            //cout<<"delete dog "<<name<<endl;
        }
};

dog::dog(){
    cout<<"blank dog"<<endl;
    this->name="blank";
}

dog::dog(const dog &d){
    cout<<"copy dog"<< " "+d.name<<endl;
    string temp=d.name;
    this->name=temp+" copied";
}


int main()
{
    dog d;
    d.name="d";
    dog dd;
    dd.name="dd";
    dog ddd;
    ddd.name="ddd";
    vector<dog> doglist;

    cout << "\nInitial capacity: " << doglist.capacity() << endl;

    doglist.push_back(d);

    cout << "After adding the first dog capacity: " << doglist.capacity() << endl;

    doglist.push_back(dd);

    cout << "After adding the second dog capacity: " << doglist.capacity() << endl;

    doglist.push_back(ddd);

    cout << "After adding the second dog capacity: " << doglist.capacity() << endl;

    return 0;
}

程序输出

blank dog
blank dog
blank dog

Initial capacity: 0
copy dog d
After adding the first dog capacity: 1
copy dog dd
copy dog d copied
After adding the second dog capacity: 2
copy dog ddd
copy dog d copied copied
copy dog dd copied
After adding the second dog capacity: 4

输出可能因矢量实现而异。

考虑到输出,您可以看到最初向量不为可能添加的元素分配内存。它的容量等于0。

当添加第一项时,向量为这一项分配内存并将提供的对象复制到此内存中。

当添加第二个项目时,向量会分配一个新的内存范围,并将新元素和第一个元素从当前内存范围复制到新的内存范围,依此类推。

你可以说它最初会为三个项目保留内存的向量。

例如

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class dog{
    public:
        string name;
        dog();
        dog(const dog & d);
        void barkname(){
            cout<<"bark "<<name<<endl;
        }
        virtual ~dog(){
            //cout<<"delete dog "<<name<<endl;
        }
};

dog::dog(){
    cout<<"blank dog"<<endl;
    this->name="blank";
}

dog::dog(const dog &d){
    cout<<"copy dog"<< " "+d.name<<endl;
    string temp=d.name;
    this->name=temp+" copied";
}


int main()
{
    dog d;
    d.name="d";
    dog dd;
    dd.name="dd";
    dog ddd;
    ddd.name="ddd";
    vector<dog> doglist;
    doglist.reserve( 3 );
    //^^^^^^^^^^^^^^^^^^^

    cout << "\nInitial capacity: " << doglist.capacity() << endl;

    doglist.push_back(d);

    cout << "After adding the first dog capacity: " << doglist.capacity() << endl;

    doglist.push_back(dd);

    cout << "After adding the second dog capacity: " << doglist.capacity() << endl;

    doglist.push_back(ddd);

    cout << "After adding the second dog capacity: " << doglist.capacity() << endl;

    return 0;
}

在这种情况下,输出看起来像

blank dog
blank dog
blank dog

Initial capacity: 3
copy dog d
After adding the first dog capacity: 3
copy dog dd
After adding the second dog capacity: 3
copy dog ddd
After adding the second dog capacity: 3

因此,在这种情况下,向量仅复制预先分配的内存范围中新添加的项目。