C++合并K个有序数组时input[i][j]方括号访问报错的原因是什么?
报错原因解答
核心根因:指针偏移步长不匹配导致类型错误
首先明确各变量的类型定义:
- 函数入参
input的类型为vector<vector<int>*>,是一个存储「指向vector<int>实例的指针」的数组 input[i]的类型为vector<int>*,是指向单个vector<int>实例的指针,并非指向vector<int>数组的首地址
C++中[]运算符对指针的操作规则是:对T*类型的指针p,p[j]等价于*(p + j),地址偏移的步长为sizeof(T):
你写input[i][j]时,T是vector<int>,所以实际等价于*( (vector<int>*)input[i] + j ),偏移的是j * sizeof(vector<int>)字节,最终得到的是vector<int>类型的对象。而你用的小顶堆pq存储的是int类型,把vector<int>对象插入int类型的队列,自然会触发编译期类型错误。
为什么input[i]->at(j)可以正常运行
input[i][j]和input[i]->at(j)的语义完全不同,不存在等价关系:
input[i]->at(j)的执行逻辑:先对vector<int>*类型的input[i]解引用,拿到对应的vector<int>实例,再调用该实例的at()方法,访问容器内部存储的第j个int元素,返回值类型为int,和队列要求的类型匹配,因此可以正常编译运行。- 如果你想通过
[]运算符访问vector内部的int元素,正确写法为(*input[i])[j]:先解引用vector<int>*指针拿到vector实例,再调用vector实例的[]运算符访问内部存储的int元素。
你之前的理解误区在于混淆了指针类型对应的偏移步长:
vector<int>*指针的偏移步长是整个vector对象的大小,而vector内部int元素的偏移步长是sizeof(int),二者完全不是一回事。
额外说明
你提到的「非法内存访问」属于运行时错误,而你遇到的是编译期类型错误,二者发生的阶段完全不同。就算你通过强制类型转换绕开编译报错,input[i][j]的语义也是访问input[i]指针往后第j个vector实例,而input[i]仅指向单个vector实例,本身就会触发非法内存访问,和vector内部元素越界的运行时错误也不属于同一类场景。
内容的提问来源于stack exchange,提问作者AK_06
相关产品推荐
相关产品推荐

