vector赋值给另一个vector_关于C++ Vector的一个小问题

已经过了8个月了。来更新一下这篇文章。在写这篇文章的时候对rvalue还不懂,所以没有意识到这里对于class A是否定义了move constructor会得到不同的结果。感谢评论区的大佬指出了其中的错误/不严谨的地方。在这儿更新一下当class A被定义了move constructor的情况。

#include <vector>
#include <iostream>
#include <iterator>

using namespace std;

int constructorCount = 0;
int copyConstructorCount = 0;
int destructorCount = 0;
int moveCntrCount = 0;

class A
{
public:
        A() {
            constructorCount++;
        }
        A(const A& src) {
            copyConstructorCount++;
        }
        A(A && src) {
          moveCntrCount++;
        }
        ~A() {
            destructorCount++;
        }
};

int main()
{
    vector<A> v;
    for (int i = 0; i < 10; ++i) {
        v.push_back(A());
    }
    cout << "Constructor: " << constructorCount << endl;
    cout << "Copy Constructor: " << copyConstructorCount << endl;
    cout << "Move Constructor: " << moveCntrCount << endl;
    cout << "Destructor: " << destructorCount << endl;
    return 0;
}

输出结果为

Constructor: 10
Copy Constructor: 15
Move Constructor: 10
Destructor: 25

唯一的区别是从copy constructor被call 25次,变成了move constructor被call 10次 + copy constructor被call 15次。因为 v.push_back(A())中A()是rvalue,所以引发了move constructor,在10次新建过程中,都触发的是move constructor。但是在reallocation的时候还是会触发copy constructor。原因在于reallocation的原因就在于原有的空间不够用,要移动到新的空间。而move constructor其实就是修改地址而不进行实际的copy,所以在原有空间不够用的情况下,并无计可施,只能老老实实用copy constructor进行copy (一共15次)。

对于rvalue的笔记也在专栏中更新,欢迎指正:

法号桑菜:lvalue, rvalue & move semantics​zhuanlan.zhihu.com

————————分割线——————————————————————

感谢评论区的很多大佬给我提了很多意见。让我发现在对class A的不同的定义情况下,会产生不同的结果。我重新更新了完整的题目代码,所以以下的问题只针对这个代码。有兴趣的读者也可以到评论区看我推荐的大佬的回复,在定义move constructor的情况下,是什么样的结果。

--------------分割线---------------------------------------------------

分享一个两年前面试一家顶级HFT(传言HFT中bar最高的)挂掉的C++题目。

题目是这样的,给下面一下段代码,问constructor, copy constructor, 以及destructor分别被使用了多少次。

#include <vector>
#include <iostream>
#include <iterator>

using namespace std;

int constructorCount = 0;
int copyConstructorCount = 0;
int destructorCount = 0;

class A
{
public:
        A() {
            constructorCount++;
        }
        A(const A& src) {
            copyConstructorCount++;
        }
        ~A() {
            destructorCount++;
        }
};

int main()
{
    vector<A> v;
    for (int i = 0; i < 10; ++i) {
        v.push_back(A());
    }
    cout << constructorCount << " " << copyConstructorCount << " " << destructorCount << endl;
    return 0;
}

要想弄清楚这个问题,最重要的就是知道push_back()发生了什么。

我们分两种情况考虑。第一种,v的capacity足够大,这里会先通过constructor构造一个class A object,然后将它用copy constructor复制到v的末尾,最后原先通过constructor构造的object会被destructor销毁掉。这种情况下,constructor,copy constructor以及destructor各被使用了一次。

第二种情况,v的capacity到了极限,这时候需要reallocate(对c++ vector capacity/reallocation不了解的读者可以先去学习一下相关知识)。这里还是会先通过constructor构造一个class A object,然后发现capacity不够大了,于是重新reallocate新的空间,把这个新的object用copy constructor复制到新的空间的相应位置。当然这个object被销毁掉也需要使用一次destructor。到这里为止,都和第一种情况是一样的。但是因为重新allocate了空间,所以我们还必须要把原有的object都复制到新的空间,并把旧的空间中的object销毁掉。这里就会额外使用x次copy constructor和destructor, x为原来capacity的大小。

于是这个问题就基本解决了。reallocation每次都会double capacity,额外的计算会发生在

capacity 0->1 (使用了0次copy constructor和destructor)

capacity 1->2 (使用了1次copy constructor和destructor)

capacity 2->4 (使用了2次copy constructor和destructor)

capacity 4->8 (使用了4次copy constructor和destructor)

capacity 8->16 (使用了8次copy constructor和destructor)

0+1+2+4+8=15

一共10个元素,总计使用了10次constructor,10+15=25次copy constructor和10+15=25次destructor。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值