c++中vector的拷贝构造过程

本文分析了C++中std::vector在push元素时构造函数、拷贝构造函数及析构函数的调用情况,并给出了具体的调用次数公式。通过实例代码详细解释了vector的内存分配策略。

c++ 中std::vector的拷贝构造过程

文章来自阿里校招的一道面试题目,向vector中push n个对象,问对象的构造函数,拷贝构造函数,析构函数分别调用了几次?

vector中的内存分配策略

vector的底层是用动态数组来存储的,当我们用vector<T> vect
这样的形式声明的时候,数组的长度是0,当我们插入第一个元素的时候,数组的长度会变为1,当插入第二个的时候,数组长度会变为2,当插入第三个元素的时候,数组长度变为4,当插入第三,第四个元素的时候,数组长度不变,当插入第五个的时候,数组长度变为8,由此我们可以看到,数组长度的分配策略:
当数组长度不够容纳新的元素时,数组长度变为原来的两倍。
(可以用vect.capacity()

拷贝构造过程

首先构造一个简单的分析过程

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

using namespace std;
int num = 0;
class Node{
public:
    int a;
    Node(int a){
        this->a = a;
        cout<<this<<" "<<"构造函数 "<<a<<endl;
    }
    Node(const Node & node){
        num++;
        this->a = node.a;
        cout<<this<<" "<<"拷贝构造函数 "<<a<<endl;
    }
    ~Node(){
        cout<<this<<" "<<"析构函数 "<<a<<endl;
    }
};
int main(){
//  freopen("in.txt", "w", stdout);
    vector<Node> vect;
    for (int i = 0; i<5; i++){
        vect.push_back(Node(i));
    } 
    cout<<num<<endl;
}

为了简单,我只push了5个元素,我们看着运行结果简单分析一下:

0x70fe30 构造函数 0
0x151540 拷贝构造函数 0
0x70fe30 析构函数 0
0x70fe30 构造函数 1
0x151a14 拷贝构造函数 1
0x151a10 拷贝构造函数 0
0x151540 析构函数 0
0x70fe30 析构函数 1
0x70fe30 构造函数 2
0x151548 拷贝构造函数 2
0x151540 拷贝构造函数 0
0x151544 拷贝构造函数 1
0x151a10 析构函数 0
0x151a14 析构函数 1
0x70fe30 析构函数 2
0x70fe30 构造函数 3
0x15154c 拷贝构造函数 3
0x70fe30 析构函数 3
0x70fe30 构造函数 4
0x151a20 拷贝构造函数 4
0x151a10 拷贝构造函数 0
0x151a14 拷贝构造函数 1
0x151a18 拷贝构造函数 2
0x151a1c 拷贝构造函数 3
0x151540 析构函数 0
0x151544 析构函数 1
0x151548 析构函数 2
0x15154c 析构函数 3
0x70fe30 析构函数 4
12
0x151a10 析构函数 0
0x151a14 析构函数 1
0x151a18 析构函数 2
0x151a1c 析构函数 3
0x151a20 析构函数 4

第一次插入的时候,容量为0:
首先构造对象,值为0,数组容量变为1,然后拷贝构造,拷贝构造的是动态数组中的元素。
第二次插入的时候,容量为1:
首先构造对象,值为1,发现数组长度不够,数组扩大为原来的2倍,然后拷贝构造1和原来的0。
第三次插入的时候,容量为2:
首先构造对象,值为2,发现数组长度不够,数组扩大为原来的2倍,然后拷贝构造2和原来的0,1。
第四次插入的时候,容量为4:
首先构造对象,值为3,发现数组可以容纳新元素,直接拷贝构造3到数组
第五次插入的时候,容量为4:
首先构造对象,值为4,发现数组长度不够,所有扩大为原来的2倍,然后拷贝构造4和原来的0,1,2,3。

结论分析

通过上面的分析,不难发现,每当发生构造函数的时候,必有一次拷贝构造伴随,然后放入数组中,多余的拷贝过程发生在数组长度不够的时候,每次扩大数组,都要把之前的元素拷贝一次,而扩大数组的时候,也正是数组插入第2n+12n+1元素的时候,这个时候,我们需要把前面的2n2n个元素拷贝一次。
所以当push n个元素到vector中:

  • 构造函数调用次数nn
  • 拷贝构造函数调用次数为
    • m = 1+2+4++2log(n1)+n1+2+4+⋯+2⌊log⁡(n−1)⌋+n
    • 析构函数调用次数: n+mn+m
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值