push_back在增加容量之前推送元素?

时间:2012-10-09 20:41:17

标签: c++ stl

class A
{
    public:
        A():a(0)
        {}
        A(int x):a(x)
        {
            cout<<"convert"<<endl;
        }
        A(const A& rhs):a(rhs.a)
        {
            cout<<"copy: "<<a<<endl;
        }
        void print()
        {
            cout<<a<<endl;
        }
        void Set(int x)
        {
            a=x;

        }
    private:
        int a;
};

int main()
{
    vector<A>vec2(2,A(100));
    cout<<"the size: "<<vec2.size()<<"  the capacity: "<<vec2.capacity()<<endl;
    vec2.push_back(17);
    for(int i=0; i<vec2.capacity();i++)
    {
        vec2[i].print();
    }
    cout<<"the size: "<<vec2.size()<<"  the capacity: "<<vec2.capacity()<<endl;
}
convert
copy: 100
copy: 100
the size: 2  the capacity: 2
convert
copy: 17
copy: 100
copy: 100
100
100
17
0

为什么会发生这种情况

copy: 17
copy: 100
copy: 100     

似乎容量是5而不是4,并且容量增加后我想要推送到矢量的元素,我一定是错的,有人可以告诉我更多细节吗?

3 个答案:

答案 0 :(得分:3)

如果您了解向量的大小和容量之间的差异,您将意识到当需要增加容量时,需要将整个向量移动到内存中的其他位置。

当向量元素从旧向量“移动”到新向量时,会发生对复制构造函数的调用。如果你添加一个带有一些调试的析构函数,那么对你来说可能更有意义。

也...

for(int i=0; i<vec2.capacity();i++)

......不是个好主意。您将访问有效矢量数据的末尾。

答案 1 :(得分:2)

在调用vec2.push_back(17)之前,大小和容量(由应用程序打印)都是2.此时,17将转换为A对象,然后传递给{ {1}}功能。在内部,push_back将缓冲区增大到更大的容量(导致std::vector的两个副本的值为100),并将A的参数复制到新分配的缓冲区中。在您的实现中,新插入的元素将在之前复制已存在的元素。

最后,当您从push_back迭代到0时,您将导致未定义的行为。您只能合法地迭代向量中从vec2.capacity()0的元素。程序的输出表明,在您的实现中,缓冲区已增长到vec2.size()(打印了4个元素)。

答案 2 :(得分:1)

你不应该使用容量的for循环。通常,容量将加倍,这是为了防止在插入新元素时出现内存损坏。

如果初始容量为2,则在添加第3个元素时它将加倍为4。当你添加第5个元素时,它的新容量将为8。