C++中删除vector元素需注意迭代器失效,推荐使用erase配合remove或remove_if实现高效删除,避免直接遍历删除导致未定义行为。

在C++中,从
std::vector
vector::erase
std::remove
std::remove_if
从
std::vector
通过迭代器或位置删除单个或一段元素:
vector
erase
erase(iterator)
iterator
erase(first, last)
first
last
last
#include <vector>
#include <iostream>
#include <algorithm> // for std::find
void print_vector(const std::vector<int>& vec, const std::string& msg = "") {
std::cout << msg;
for (int x : vec) {
std::cout << x << " ";
}
std::cout << std::endl;
}
int main() {
std::vector<int> nums = {10, 20, 30, 40, 50};
print_vector(nums, "原始vector: "); // 10 20 30 40 50
// 删除特定位置的元素 (例如,删除第三个元素 30)
// 注意:vector的索引从0开始,所以第三个元素是索引2
auto it_to_erase = nums.begin() + 2; // 指向30
nums.erase(it_to_erase);
print_vector(nums, "删除索引2元素后: "); // 10 20 40 50
// 删除一段范围的元素 (例如,删除 20 和 40)
// 找到20的位置
auto it_start = std::find(nums.begin(), nums.end(), 20);
// 找到40的位置 (如果40存在且在20之后)
auto it_end = std::find(nums.begin(), nums.end(), 40);
if (it_start != nums.end() && it_end != nums.end()) {
nums.erase(it_start, it_end); // 删除从20到40(不含40)
}
print_vector(nums, "删除20到40(不含40)后: "); // 10 40 50 (如果之前是10 20 40 50,这里会删除20)
// 实际上,由于40是下一个元素,它会删除20
// 让我们重新演示一个更清晰的范围删除
nums = {10, 20, 30, 40, 50, 60};
print_vector(nums, "重新初始化vector: "); // 10 20 30 40 50 60
// 删除从索引1 (20) 到索引4 (50) 之间的元素,不包含索引4 (即删除 20, 30, 40)
nums.erase(nums.begin() + 1, nums.begin() + 4);
print_vector(nums, "删除索引1到4(不含4)后: "); // 10 50 60
}通过值删除(“remove-erase”惯用法): 如果你想删除所有值为特定
X
erase
std::remove
vector::erase
std::remove
vector
vector::erase
vector
#include <vector>
#include <iostream>
#include <algorithm> // for std::remove
int main() {
std::vector<int> nums = {10, 20, 30, 20, 40, 50, 20};
print_vector(nums, "原始vector: "); // 10 20 30 20 40 50 20
// 删除所有值为20的元素
// std::remove 将所有非20的元素移到前面,并返回新逻辑末尾的迭代器
auto new_end = std::remove(nums.begin(), nums.end(), 20);
// erase 删除从 new_end 到 nums.end() 之间的元素
nums.erase(new_end, nums.end());
print_vector(nums, "删除所有20后: "); // 10 30 40 50
}条件删除(std::remove_if
vector::erase
std::remove_if
std::remove
bool
true
#include <vector>
#include <iostream>
#include <algorithm> // for std::remove_if
int main() {
std::vector<int> nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
print_vector(nums, "原始vector: "); // 1 2 3 4 5 6 7 8 9 10
// 删除所有偶数
auto new_end = std::remove_if(nums.begin(), nums.end(), [](int n){
return n % 2 == 0; // 谓词:如果是偶数则返回true
});
nums.erase(new_end, nums.end());
print_vector(nums, "删除所有偶数后: "); // 1 3 5 7 9
}当顺序不重要时,更高效的删除单个元素: 如果你只需要删除一个特定元素,并且
vector
vector
pop_back
erase
#include <vector>
#include <iostream>
#include <algorithm> // for std::find
int main() {
std::vector<int> nums = {10, 20, 30, 40, 50};
print_vector(nums, "原始vector: "); // 10 20 30 40 50
// 假设要删除元素30,但顺序不重要
auto it = std::find(nums.begin(), nums.end(), 30);
if (it != nums.end()) {
*it = nums.back(); // 将最后一个元素的值赋给要删除的元素
nums.pop_back(); // 删除最后一个元素
}
print_vector(nums, "删除30(顺序不重要)后: "); // 10 20 50 40 (或 10 20 40 50,取决于具体实现,但30肯定没了)
// 实际输出会是 10 20 50 40
}这几乎是所有C++新手在处理
vector
std::vector
核心问题在于迭代器失效。当
vector::erase()
立即学习“C++免费学习笔记(深入)”;
erase()
如果你在一个
for
for (auto it = vec.begin(); it != vec.end(); ++it)
vec.erase(it)
it
erase
++it
错误示例:
#include <vector>
#include <iostream>
int main() {
std::vector<int> nums = {1, 2, 3, 4, 5};
std::cout << "原始vector: ";
for (int n : nums) std::cout << n << " ";
std::cout << std::endl;
// 尝试删除所有偶数(错误的方式)
for (auto it = nums.begin(); it != nums.end(); ++it) {
if (*it % 2 == 0) {
nums.erase(it); // 此时it失效
// 问题:下一个循环迭代会尝试递增一个失效的it,导致未定义行为
// 如果不加处理,甚至可能跳过下一个元素
}
}
// 实际运行可能会崩溃,或者输出错误结果
std::cout << "删除偶数后(错误方式): ";
for (int n : nums) std::cout << n << " ";
std::cout << std::endl; // 结果通常不正确或崩溃
return 0;
}正确的处理方式: 始终使用
erase
#include <vector>
#include <iostream>
int main() {
std::vector<int> nums = {1, 2, 3, 4, 5, 6};
std::cout << "原始vector: ";
for (int n : nums) std::cout << n << " ";
std::cout << std::endl;
// 正确删除所有偶数的方式 (虽然效率不如remove-erase,但可以这样操作)
for (auto it = nums.begin(); it != nums.end(); ) { // 注意这里没有 ++it
if (*it % 2 == 0) {
it = nums.erase(it); // erase返回指向下一个元素的有效迭代器
} else {
++it; // 如果没有删除,则正常前进
}
}
std::cout << "删除偶数后(正确方式): ";
for (int n : nums) std::cout << n << " ";
std::cout << std::endl; // 1 3 5
return 0;
}即便如此,这种在循环中频繁调用
erase
std::remove
vector::erase
std::remove
vector::erase
vector
std::remove
首先要明确,
std::remove
std::remove_if
想象一下,你有一排书,想把所有红色的书扔掉。
std::remove
vector::erase
std::remove
vector::erase
vector::erase(new_end, nums.end())
new_end
nums.end()
vector
size()
通过这种分工,
std::remove
vector::erase
erase
erase
示例再次强调:
#include <vector>
#include <iostream>
#include <algorithm> // for std::remove
int main() {
std::vector<int> data = {1, 5, 2, 5, 3, 5, 4};
print_vector(data, "原始数据: "); // 1 5 2 5 3 5 4
// 假设我们要删除所有值为5的元素
// 步骤1: std::remove
// 它会将 {1, 2, 3, 4, ?, ?, ?} 这样的结构,并返回指向第一个?的迭代器
auto new_end_it = std::remove(data.begin(), data.end(), 5);
print_vector(data, "std::remove后 (注意大小不变,但内容已重排): "); // 1 2 3 4 3 5 4 (后面的值是未定义的,取决于实现)
// 这里只是一个示例,实际值可能是任何东西,但前四个是正确的
// 步骤2: vector::erase
// 它会删除从 new_end_it 到 data.end() 的所有元素
data.erase(new_end_it, data.end());
print_vector(data, "std::remove + vector::erase 后: "); // 1 2 3 4
}这种模式不仅清晰,而且对于
vector
删除
vector
性能影响:元素的移动开销 当你在
vector
vector
memmove
erase(iterator)
vector
i
N - 1 - i
erase(first, last)
k
N - k - (first_index)
remove-erase
std::remove
vector::erase
erase
pop_back
swap
pop_back
频繁地在
vector
std::vector
std::list
std::deque
内存影响:容量(Capacity)与大小(Size)
vector
size()
capacity()
erase
size()
capacity()
以上就是如何在C++中从vector中删除一个元素_C++ vector元素删除操作详解的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号