C++中Vector元素索引查找、删除及循环条件下元素增删的代码报错求助
Let's walk through the issues in your code and get it working correctly. I'll break down each problem clearly, then show you the corrected version.
Key Issues in Your Code
1. Wrong Type for std::find Result
You tried assigning the output of std::find (an iterator) to a std::vector<Arrow*>, which is invalid. std::find returns an iterator pointing to the found element (or the end of the range if nothing was found), not a full vector.
2. Misused std::distance
std::distance requires two iterators from the same sequence. You passed the vector itself as the first argument, but you should have used the vector's beginning iterator. That said, you don't even need std::distance here—we can erase directly using the iterator we get from std::find.
3. Invalid vector::erase Call
Your erase attempt uses nonsensical arguments: itr.begin() doesn't exist (since itr is an iterator, not a container), and passing an integer index as the second argument won't work because erase expects iterators for range operations. For removing a single element, you only need to pass the iterator directly.
4. Logical Error in Search Target
You're searching for arrows[i] (a unique_ptr<Arrow>) in a vector of Arrow* pointers. But you should be searching for arrows[j].get()—the exact pointer you added in the if clause. This would have meant your code never found the element to remove, even when the condition was false.
5. Missing Valid Iterator Check
Before erasing, you must confirm std::find actually found the element (i.e., the iterator isn't equal to vector::end()). Erasing the end iterator is undefined behavior.
Corrected Code
#include <iterator> #include <vector> #include <algorithm> #include <memory> struct Arrow { std::vector<Arrow*> inRange; }; int main() { std::vector<std::unique_ptr<Arrow>> arrows; for (int i = 0; i < 10; i++) arrows.push_back(std::make_unique<Arrow>()); for (int i = 0; i < arrows.size(); i++) { for (int j = 0; j < arrows.size(); j++) { if (i != j) { bool someCondition = true; // Adjust this value as needed for your logic if (someCondition) { arrows[i]->inRange.push_back(arrows[j].get()); } else { // Get the exact pointer we want to remove Arrow* target = arrows[j].get(); // Find the iterator pointing to that pointer auto itr = std::find(arrows[i]->inRange.begin(), arrows[i]->inRange.end(), target); // Only erase if we actually found the element if (itr != arrows[i]->inRange.end()) { arrows[i]->inRange.erase(itr); } } } } } return 0; }
Key Takeaways
- Use
autofor iterators to avoid typing complex container iterator types and reduce errors. - Always verify that
std::findreturned a valid iterator (notend()) before attempting to erase. - When removing a single element from a vector, pass the direct iterator to
erase()—no need to calculate indices or ranges. - Double-check that you're searching for the exact value stored in the container (in this case,
Arrow*pointers, notunique_ptr<Arrow>objects).
内容的提问来源于stack exchange,提问作者Apple_Banana

