C++中存储双指针的vector迭代时元素值异常变化问题求助
嘿,我来帮你捋捋这个vector的问题~
问题根源
你遇到的核心问题其实是存储了同一个局部变量的地址,导致所有vector元素都指向同一个地方。
看你这段代码:
TreeNode* tmp; vertexQueue.push(Tree); while (!vertexQueue.empty()) { tmp = vertexQueue.front(); vertexQueue.pop(); vertexVector.emplace_back(&tmp); // ... 输出逻辑 }
这里的tmp是在循环外面定义的单个指针变量,整个循环过程中它的内存地址是固定不变的。每次循环你只是把tmp的值更新成队列弹出的新节点,但&tmp永远指向同一个内存位置。所以vertexVector里的所有TreeNode**元素,本质上都指向同一个tmp变量。当你下次循环更新tmp的值时,所有通过vector元素解引用得到的结果自然都会跟着变——因为它们都是在访问同一个tmp呀!
两种解决思路
根据你的需求,这里有两种常用的修正方式:
思路1:直接存储TreeNode*(推荐,最简单)
如果你的场景不需要二级指针,直接把vector的类型改成std::vector<TreeNode*>就搞定了:
std::queue<TreeNode*> vertexQueue; std::vector<TreeNode*> vertexVector; // 改成存储一级指针 TreeNode* tmp; vertexQueue.push(Tree); while (!vertexQueue.empty()) { tmp = vertexQueue.front(); vertexQueue.pop(); vertexVector.push_back(tmp); // 直接存节点指针 // 输出逻辑调整下: for (int i = 0; i < vertexVector.size(); i++) { std::cout << vertexVector[i]->info.weigth << ' '; } std::cout << std::endl; if (!isLeave(tmp)) { vertexQueue.push(tmp->leftBranch); vertexQueue.push(tmp->rigthBranch); } }
这样每个vector元素都是独立的节点指针,指向队列中弹出的不同节点,再也不会出现全部同步变化的问题了。
思路2:必须用二级指针的场景(谨慎使用)
如果你确实需要用TreeNode**类型的vector,那得给每个节点分配独立的一级指针存储空间,不能复用同一个tmp:
std::queue<TreeNode*> vertexQueue; std::vector<TreeNode**> vertexVector; vertexQueue.push(Tree); while (!vertexQueue.empty()) { // 把tmp移到循环里,每次创建新的指针变量 TreeNode* tmp = vertexQueue.front(); vertexQueue.pop(); vertexVector.emplace_back(&tmp); // 输出逻辑不变 for (int i = 0; i < vertexVector.size(); i++) { std::cout << (*vertexVector[i])->info.weigth << ' '; } std::cout << std::endl; if (!isLeave(tmp)) { vertexQueue.push(tmp->leftBranch); vertexQueue.push(tmp->rigthBranch); } }
⚠️ 注意:这种方式里循环内的tmp是栈上的局部变量,循环结束后这个变量就销毁了,后续再访问vector里的指针会触发未定义行为。如果要安全使用,得用动态分配的指针:
std::queue<TreeNode*> vertexQueue; std::vector<TreeNode**> vertexVector; vertexQueue.push(Tree); while (!vertexQueue.empty()) { // 动态分配一级指针 TreeNode** tmpPtr = new TreeNode*; *tmpPtr = vertexQueue.front(); vertexQueue.pop(); vertexVector.push_back(tmpPtr); // 输出逻辑调整下: for (int i = 0; i < vertexVector.size(); i++) { std::cout << (*(*vertexVector[i]))->info.weigth << ' '; } std::cout << std::endl; if (!isLeave(*tmpPtr)) { vertexQueue.push((*tmpPtr)->leftBranch); vertexQueue.push((*tmpPtr)->rigthBranch); } } // 记得最后释放内存,避免泄漏 for (auto ptr : vertexVector) { delete ptr; }
但这种方式会增加内存管理的复杂度,所以没有特殊需求的话,优先选思路1就好。
内容的提问来源于stack exchange,提问作者Gleb Bessudnov
相关产品推荐
相关产品推荐

