关于vector使用的忠告
查看原帖
关于vector使用的忠告
368884
sunrise1024楼主2024/7/27 20:55

众所周知,vector 是一种可变长度的容器,它会在分配容量用完以后整体移动到另外的位置并分配于原先两倍的容量。

根据这个特性,不要在会改变 vector 长度的函数中传引用,例如:merge(node& left_tree,node& right_tree) ,如果这个函数会新建节点(因为要可持久化),就可能导致传进来的引用失效,无法修改到我们希望的值。

另外,c++ 的赋值 a=b 等价于 a.operator=(b) ,所以左边的地址在右边的运算进行之前就已经被固定了,也就是说如果右边是一个函数调用,而且这个函数会改变 vector 的大小,也可能导致赋值到我们不希望的位置。

具体的,例如以下代码:

#include<bits/stdc++.h>
using namespace std;
vector<int> a;
int calc(){
    for(int i=1;i<=10;++i)a.push_back(1);
    return 114514;
}
int main(){
    a.push_back(0);
    int* b=&a[0];
    a[0]=calc();
    cout<<a[0]<<' '<<*b;
    return 0;
}

因为 calc 函数改变了 a 的大小,导致 a 换地方了,所以最终的输出就是 0 114514 。

所以如果像我一样写了类似 t[no].s[0]=merge(k0,t[no].s[0]) 的表达,其中 merge 改变了 vector 的长度,就可能导致赋值失效。

解决这两个问题有两种方法,一是不要这么写,二是使用 reserve 函数,vector.reserve(n) 就相当于为 vector 分配了 n 的容量,直接给 vector 初始分配巨大的容量就不会导致 vector 用完容量以后乱跑了。

2024/7/27 20:55
加载中...