C++通过指针遍历vector<Apple*>元素输出0的问题求解
问题根因
你的代码错误来自对指针算术逻辑的误解:
- 你定义的
Apple* ptr = apples[0]是直接指向第一个new出来的Apple实例的指针,三个Apple实例是独立调用new分配的堆内存,内存地址不连续。对ptr执行++操作时,指针会向后偏移1个Apple对象的内存长度,这个偏移后的地址不属于任何你创建的Apple实例,属于非法野指针访问,读到的是内存里的随机值,所以输出0。 - vector内的元素确实是连续存储的,但你存的元素类型是
Apple*,连续排列的是这些指针本身,不是指针指向的Apple对象。你拿第一个Apple对象的地址做偏移,根本访问不到vector里存的下一个指针。
正确实现
给你三种可直接运行的正确遍历写法,包含你之前尝试没写对的迭代器版本:
#include <iostream> #include <vector> class Apple{ public: int size; Apple(int size): size(size){} void print(){ std::cout << size << '\n'; } }; std::vector<Apple*> apples = {new Apple(21), new Apple(37), new Apple(66)}; // 1. 迭代器遍历(你之前尝试的错误写法是没搞懂迭代器的解引用层级) void traverseByIterator() { for (auto it = apples.begin(); it != apples.end(); ++it) { // it是指向vector元素的迭代器,*it拿到vector里存的Apple*指针,再用->访问对象成员 (*it)->print(); } } // 2. 指针对齐偏移遍历(对应你原来想写的ptr自增逻辑) void traverseByPointer() { // 要定义指向vector元素的二级指针,因为vector存的元素是Apple*,元素首地址类型是Apple** Apple** ptr = apples.data(); for (size_t i = 0; i < apples.size(); ++i) { (*ptr)->print(); ptr++; // 每次偏移一个Apple*的长度,刚好走到下一个连续存储的vector元素 } } // 3. 最简洁的范围for遍历 void traverseByRangeFor() { for (auto applePtr : apples) { applePtr->print(); } } int main() { traverseByIterator(); // 用完记得释放new出来的对象,避免内存泄漏 for (auto p : apples) { delete p; } return 0; }
注意事项
- 只有指向同一块连续内存(比如数组、vector内部存储块)的指针,做自增偏移访问后续元素才是合法行为,独立分配的堆对象地址没有连续性保证。
- 存储指针的容器遍历要注意解引用层级:迭代器/下标拿到的是容器里存的指针,需要再访问一次才能拿到指向的对象。
- 所有手动
new出来的堆对象,必须在使用完后手动delete,否则会造成内存泄漏。
内容的提问来源于stack exchange,提问作者kolodziejpawel98
相关产品推荐
相关产品推荐

