C++两种vector初始化方式的区别及vector adj[x]是否为二维vector初始化
结论
vector<int> adj[2] 不属于二维vector的初始化方式,二者本质完全不同。
两种写法的本质定义
你给出的两段代码从存储元素的维度看,都可以实现类似「二维数组」的访问效果(比如都支持test[0].push_back(1)、adj[0].push_back(1)写法),但底层实现逻辑有本质区别:
vector<vector<int>> test(2):是完全由STL容器实现的动态二维数组,外层是一个vector容器,容器内的每个元素都是vector<int>类型,初始化时指定外层vector的长度为2,两个元素默认是空的int型vector。vector<int> adj[2]:是存储vector<int>元素的原生C++数组,外层是长度固定为2的原生数组,数组内的每个元素是vector<int>类型。
核心差异对比
动态性不同
test作为STL vector,外层长度支持动态修改,你可以随时调用test.push_back()、test.resize()等方法调整外层的元素数量,长度参数支持传入运行期变量(比如int n; cin >> n; vector<vector<int>> test(n);是完全合法的标准C语法)。adj作为原生数组,外层长度在标准C中要求必须是编译期常量,后续无法修改外层数组的总长度,也没有size()、push_back()这类容器方法。如果用变量作为数组长度(比如int x; cin >>x; vector<int> adj[x];),属于GCC等编译器的扩展特性(变长数组VLA),不属于标准C++,可移植性极差。语法特性不同
test是完整的STL容器,原生支持所有STL算法调用、范围for循环遍历,作为参数传递给函数时可以保留完整的长度信息。adj作为原生数组,传递给函数时会自动退化为指针,丢失外层长度信息,仅能修改每个数组元素(也就是内部的vector<int>)的内容。内存存储位置不同
test的外层vector结构本身和内部存储的元素都在堆内存分配,不存在栈溢出风险。
如果adj是局部变量声明的原生数组,数组本身的结构存储在栈内存,当数组长度过大时会触发栈溢出。
为什么GDB打印结果看起来相似?
你给出的GDB打印输出展示的是两种结构内部存储的元素内容,两段代码里的元素都是2个空的vector<int>,所以输出看起来高度相似。你可以分别打印test.size()和sizeof(adj)验证差异:前者是vector的成员方法,返回外层容器的当前长度;后者返回的是整个原生数组占用的总字节数,二者逻辑完全不同。
内容的提问来源于stack exchange,提问作者Nabz C

