@ohos-graphics/stability-code-review 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +169 -0
- package/SKILL.md +518 -0
- package/bin/install.js +165 -0
- package/config/rules.yaml +445 -0
- package/config/whitelist.yaml +52 -0
- package/package.json +40 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_001.md +275 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_002.md +273 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_003.md +305 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_004.md +350 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_005.md +301 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_006.md +320 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_007.md +432 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_008.md +394 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_009.md +425 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_010.md +472 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_011.md +204 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_012.md +210 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_013.md +226 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_014.md +222 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_015.md +256 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_016.md +269 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_017.md +222 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_018.md +336 -0
- package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_001.md +414 -0
- package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_002.md +335 -0
- package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_003.md +284 -0
- package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_004.md +313 -0
- package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_005.md +364 -0
- package/references/ExceptionHandling/StabilityCodeReview_ExceptionHandling_001.md +142 -0
- package/references/ExceptionHandling/StabilityCodeReview_ExceptionHandling_002.md +222 -0
- package/references/ExceptionHandling/StabilityCodeReview_ExceptionHandling_003.md +383 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_001.md +258 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_002.md +131 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_003.md +220 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_004.md +224 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_005.md +250 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_006.md +153 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_007.md +169 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_008.md +153 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_009.md +144 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_010.md +152 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_011.md +221 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_012.md +318 -0
- package/references/InitializationOrder/StabilityCodeReview_InitializationOrder_001.md +411 -0
- package/references/Lifecycle/StabilityCodeReview_Lifecycle_001.md +255 -0
- package/references/Lifecycle/StabilityCodeReview_Lifecycle_002.md +177 -0
- package/references/MemoryStability/StabilityCodeReview_MemoryStability_001.md +332 -0
- package/references/MemoryStability/StabilityCodeReview_MemoryStability_002.md +261 -0
- package/references/MemoryStability/StabilityCodeReview_MemoryStability_003.md +428 -0
- package/references/MemoryStability/StabilityCodeReview_MemoryStability_004.md +400 -0
- package/references/MemoryStability/StabilityCodeReview_MemoryStability_005.md +364 -0
- package/references/MemoryStability/StabilityCodeReview_MemoryStability_006.md +359 -0
- package/references/MemoryStability/StabilityCodeReview_MemoryStability_007.md +279 -0
- package/references/PROBLEM_TEMPLATE.md +65 -0
- package/references/PerformanceStability/StabilityCodeReview_PerformanceStability_001.md +380 -0
- package/references/PerformanceStability/StabilityCodeReview_PerformanceStability_002.md +437 -0
- package/references/REPORT_TEMPLATE.csv +5 -0
- package/references/REPORT_TEMPLATE.md +132 -0
- package/references/RULE_DEVELOPMENT_GUIDE.md +711 -0
- package/references/RULE_INDEX.md +101 -0
- package/references/RULE_TEMPLATE.md +192 -0
- package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_001.md +334 -0
- package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_002.md +425 -0
- package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_003.md +420 -0
- package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_004.md +409 -0
- package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_005.md +445 -0
- package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_006.md +384 -0
- package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_007.md +395 -0
- package/scripts/add-rule.py +423 -0
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
---
|
|
2
|
+
rule_id: "StabilityCodeReview_BoundaryCondition_008"
|
|
3
|
+
name: "容器erase后需正确更新迭代器"
|
|
4
|
+
category: "边界条件"
|
|
5
|
+
severity: "HIGH"
|
|
6
|
+
language: ["cpp", "c++"]
|
|
7
|
+
author: "OH-Department7 Stability Team"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# 容器erase后需正确更新迭代器
|
|
11
|
+
|
|
12
|
+
## 问题描述
|
|
13
|
+
|
|
14
|
+
容器erase后需要正确更新迭代器,避免使用失效的迭代器。erase操作会使当前迭代器失效,继续使用会导致未定义行为、程序崩溃或内存访问错误。
|
|
15
|
+
|
|
16
|
+
## 检测示例
|
|
17
|
+
|
|
18
|
+
### ❌ 问题代码
|
|
19
|
+
|
|
20
|
+
```cpp
|
|
21
|
+
// 错误示例1:erase后继续使用迭代器
|
|
22
|
+
void RemoveElements(std::vector<int>& vec)
|
|
23
|
+
{
|
|
24
|
+
for (auto it = vec.begin(); it != vec.end(); ++it) {
|
|
25
|
+
if (*it < 0) {
|
|
26
|
+
vec.erase(it); // 危险:erase后迭代器失效
|
|
27
|
+
++it; // 错误:使用失效的迭代器
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// 错误示例2:erase后未更新迭代器
|
|
33
|
+
void RemoveItems(std::list<int>& list)
|
|
34
|
+
{
|
|
35
|
+
for (auto it = list.begin(); it != list.end(); ++it) {
|
|
36
|
+
if (*it == 0) {
|
|
37
|
+
list.erase(it); // 危险:erase后迭代器失效
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 错误示例3:erase后直接访问
|
|
43
|
+
void ProcessMap(std::map<int, std::string>& map)
|
|
44
|
+
{
|
|
45
|
+
for (auto it = map.begin(); it != map.end(); ++it) {
|
|
46
|
+
if (it->second.empty()) {
|
|
47
|
+
map.erase(it); // 危险:erase后迭代器失效
|
|
48
|
+
std::string key = std::to_string(it->first); // 错误:访问失效迭代器
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 错误示例4:erase后继续遍历
|
|
54
|
+
void RemoveBadItems(std::vector<Item>& items)
|
|
55
|
+
{
|
|
56
|
+
for (auto it = items.begin(); it != items.end(); ++it) {
|
|
57
|
+
if (it->IsBad()) {
|
|
58
|
+
items.erase(it); // 危险:迭代器失效
|
|
59
|
+
// 继续使用++it遍历
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 错误示例5:嵌套erase
|
|
65
|
+
void RemoveNested(std::vector<std::vector<int>>& data)
|
|
66
|
+
{
|
|
67
|
+
for (auto outer = data.begin(); outer != data.end(); ++outer) {
|
|
68
|
+
for (auto inner = outer->begin(); inner != outer->end(); ++inner) {
|
|
69
|
+
if (*inner == 0) {
|
|
70
|
+
outer->erase(inner); // 危险:内层迭代器失效
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// 错误示例6:erase后访问前一个元素
|
|
77
|
+
void RemoveAndAccess(std::vector<int>& vec)
|
|
78
|
+
{
|
|
79
|
+
auto prev = vec.begin();
|
|
80
|
+
for (auto it = vec.begin(); it != vec.end(); ++it) {
|
|
81
|
+
if (*it == 5) {
|
|
82
|
+
vec.erase(it);
|
|
83
|
+
int value = *prev; // 错误:prev可能也已失效
|
|
84
|
+
}
|
|
85
|
+
prev = it;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// 错误示例7:set容器erase
|
|
90
|
+
void RemoveSetItems(std::set<int>& set)
|
|
91
|
+
{
|
|
92
|
+
for (auto it = set.begin(); it != set.end(); ++it) {
|
|
93
|
+
if (*it > 100) {
|
|
94
|
+
set.erase(it); // 危险:迭代器失效
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// 错误示例8:erase返回值未使用
|
|
100
|
+
void RemoveValues(std::vector<int>& vec)
|
|
101
|
+
{
|
|
102
|
+
for (auto it = vec.begin(); it != vec.end(); ++it) {
|
|
103
|
+
if (*it == 0) {
|
|
104
|
+
vec.erase(it); // 错误:未使用erase返回值更新迭代器
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// 错误示例9:删除后立即访问
|
|
110
|
+
void RemoveAndCheck(std::list<int>& list)
|
|
111
|
+
{
|
|
112
|
+
auto it = list.begin();
|
|
113
|
+
while (it != list.end()) {
|
|
114
|
+
if (*it == 0) {
|
|
115
|
+
list.erase(it);
|
|
116
|
+
if (it != list.end()) { // 错误:it已失效
|
|
117
|
+
++it;
|
|
118
|
+
}
|
|
119
|
+
} else {
|
|
120
|
+
++it;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// 错误示例10:clear后使用迭代器
|
|
126
|
+
void ClearAndAccess(std::vector<int>& vec)
|
|
127
|
+
{
|
|
128
|
+
auto it = vec.begin();
|
|
129
|
+
vec.clear(); // 危险:所有迭代器失效
|
|
130
|
+
if (it != vec.end()) { // 错误:使用失效迭代器
|
|
131
|
+
// ...
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### ✅ 修复方案
|
|
137
|
+
|
|
138
|
+
```cpp
|
|
139
|
+
// 正确示例1:使用erase返回值更新迭代器
|
|
140
|
+
void RemoveElements(std::vector<int>& vec)
|
|
141
|
+
{
|
|
142
|
+
for (auto it = vec.begin(); it != vec.end(); ) {
|
|
143
|
+
if (*it < 0) {
|
|
144
|
+
it = vec.erase(it); // 正确:使用返回值更新
|
|
145
|
+
} else {
|
|
146
|
+
++it; // 正确:只在未erase时递增
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// 正确示例2:list容器erase更新
|
|
152
|
+
void RemoveItems(std::list<int>& list)
|
|
153
|
+
{
|
|
154
|
+
for (auto it = list.begin(); it != list.end(); ) {
|
|
155
|
+
if (*it == 0) {
|
|
156
|
+
it = list.erase(it); // 正确:使用返回值
|
|
157
|
+
} else {
|
|
158
|
+
++it;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// 正确示例3:map容器erase更新
|
|
164
|
+
void ProcessMap(std::map<int, std::string>& map)
|
|
165
|
+
{
|
|
166
|
+
for (auto it = map.begin(); it != map.end(); ) {
|
|
167
|
+
if (it->second.empty()) {
|
|
168
|
+
it = map.erase(it); // 正确:使用返回值
|
|
169
|
+
} else {
|
|
170
|
+
++it;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// 正确示例4:使用remove_if和erase组合
|
|
176
|
+
void RemoveBadItems(std::vector<Item>& items)
|
|
177
|
+
{
|
|
178
|
+
items.erase(
|
|
179
|
+
std::remove_if(items.begin(), items.end(),
|
|
180
|
+
[](const Item& item) { return item.IsBad(); }),
|
|
181
|
+
items.end()
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// 正确示例5:嵌套容器安全删除
|
|
186
|
+
void RemoveNested(std::vector<std::vector<int>>& data)
|
|
187
|
+
{
|
|
188
|
+
for (auto outer = data.begin(); outer != data.end(); ) {
|
|
189
|
+
for (auto inner = outer->begin(); inner != outer->end(); ) {
|
|
190
|
+
if (*inner == 0) {
|
|
191
|
+
inner = outer->erase(inner); // 正确:使用返回值
|
|
192
|
+
} else {
|
|
193
|
+
++inner;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (outer->empty()) {
|
|
197
|
+
outer = data.erase(outer); // 正确:使用返回值
|
|
198
|
+
} else {
|
|
199
|
+
++outer;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// 正确示例6:使用索引而非迭代器
|
|
205
|
+
void RemoveAndAccess(std::vector<int>& vec)
|
|
206
|
+
{
|
|
207
|
+
for (size_t i = 0; i < vec.size(); ) {
|
|
208
|
+
if (vec[i] == 5) {
|
|
209
|
+
vec.erase(vec.begin() + i); // 正确:索引访问安全
|
|
210
|
+
} else {
|
|
211
|
+
++i;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// 正确示例7:set容器安全删除
|
|
217
|
+
void RemoveSetItems(std::set<int>& set)
|
|
218
|
+
{
|
|
219
|
+
for (auto it = set.begin(); it != set.end(); ) {
|
|
220
|
+
if (*it > 100) {
|
|
221
|
+
it = set.erase(it); // 正确:使用返回值
|
|
222
|
+
} else {
|
|
223
|
+
++it;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// 正确示例8:使用lambda和erase
|
|
229
|
+
void RemoveValues(std::vector<int>& vec)
|
|
230
|
+
{
|
|
231
|
+
vec.erase(std::remove(vec.begin(), vec.end(), 0), vec.end());
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// 正确示例9:安全的while循环删除
|
|
235
|
+
void RemoveAndCheck(std::list<int>& list)
|
|
236
|
+
{
|
|
237
|
+
auto it = list.begin();
|
|
238
|
+
while (it != list.end()) {
|
|
239
|
+
if (*it == 0) {
|
|
240
|
+
it = list.erase(it); // 正确:使用返回值
|
|
241
|
+
} else {
|
|
242
|
+
++it;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// 正确示例10:clear后重新获取迭代器
|
|
248
|
+
void ClearAndAccess(std::vector<int>& vec)
|
|
249
|
+
{
|
|
250
|
+
vec.clear();
|
|
251
|
+
auto it = vec.begin(); // 正确:clear后重新获取迭代器
|
|
252
|
+
if (it != vec.end()) {
|
|
253
|
+
// ...
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// 正确示例11:使用C++11的erase返回值
|
|
258
|
+
template<typename Container, typename Predicate>
|
|
259
|
+
void RemoveIf(Container& container, Predicate pred)
|
|
260
|
+
{
|
|
261
|
+
for (auto it = container.begin(); it != container.end(); ) {
|
|
262
|
+
if (pred(*it)) {
|
|
263
|
+
it = container.erase(it);
|
|
264
|
+
} else {
|
|
265
|
+
++it;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## 检测范围
|
|
272
|
+
|
|
273
|
+
检查以下模式:
|
|
274
|
+
|
|
275
|
+
1. `container.erase(it)` 后使用 `++it`
|
|
276
|
+
2. `container.erase(it)` 后访问 `*it` 或 `it->member`
|
|
277
|
+
3. erase后未更新迭代器继续遍历
|
|
278
|
+
4. clear后使用旧迭代器
|
|
279
|
+
|
|
280
|
+
## 检测要点
|
|
281
|
+
|
|
282
|
+
1. 识别`erase`函数调用
|
|
283
|
+
2. 检查erase后是否使用返回值更新迭代器
|
|
284
|
+
3. 检查erase后是否继续使用原迭代器
|
|
285
|
+
4. 识别`clear`后迭代器使用
|
|
286
|
+
5. 排除NOPROTECT标记的代码
|
|
287
|
+
|
|
288
|
+
## 风险流分析(RiskFlow)
|
|
289
|
+
|
|
290
|
+
- **RISK_SOURCE**: erase操作后迭代器失效
|
|
291
|
+
- **RISK_TYPE**: 使用失效迭代器
|
|
292
|
+
- **RISK_PATH**: erase -> 迭代器失效 -> 继续使用 -> 未定义行为
|
|
293
|
+
- **IMPACT_POINT**: 程序崩溃、内存访问错误
|
|
294
|
+
|
|
295
|
+
## 影响分析(ImpactAnalysis)
|
|
296
|
+
|
|
297
|
+
- **Trigger**: erase后未正确更新迭代器
|
|
298
|
+
- **Propagation**: 失效迭代器导致内存访问错误
|
|
299
|
+
- **Consequence**: 程序崩溃、数据损坏、未定义行为
|
|
300
|
+
- **Mitigation**: 使用erase返回值更新迭代器,或使用remove_if
|
|
301
|
+
|
|
302
|
+
## 误报排除
|
|
303
|
+
|
|
304
|
+
| 场景 | 识别特征 | 处理方式 |
|
|
305
|
+
|------|----------|----------|
|
|
306
|
+
| NOPROTECT 标记 | 有 // NOPROTECT 注释 | 不报 |
|
|
307
|
+
| 使用erase返回值 | it = container.erase(it) | 不报 |
|
|
308
|
+
| remove_if模式 | 使用std::remove_if | 不报 |
|
|
309
|
+
| 重新获取迭代器 | erase后重新begin() | 不报 |
|
|
310
|
+
| 第三方库 | 位于 third_party 目录 | 白名单排除 |
|
|
311
|
+
## 测试用例
|
|
312
|
+
|
|
313
|
+
### 触发用例(应该报)
|
|
314
|
+
|
|
315
|
+
```cpp
|
|
316
|
+
// test_BoundaryCondition_008_trigger.cpp
|
|
317
|
+
void trigger_bad_1(std::vector<int>& vec)
|
|
318
|
+
{
|
|
319
|
+
for (auto it = vec.begin(); it != vec.end(); ++it) {
|
|
320
|
+
if (*it < 0) {
|
|
321
|
+
vec.erase(it); // 应该报:erase后++it
|
|
322
|
+
++it;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
void trigger_bad_2(std::list<int>& list)
|
|
328
|
+
{
|
|
329
|
+
for (auto it = list.begin(); it != list.end(); ++it) {
|
|
330
|
+
if (*it == 0) {
|
|
331
|
+
list.erase(it); // 应该报:erase后继续遍历
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
void trigger_bad_3(std::map<int, std::string>& map)
|
|
337
|
+
{
|
|
338
|
+
for (auto it = map.begin(); it != map.end(); ++it) {
|
|
339
|
+
if (it->second.empty()) {
|
|
340
|
+
map.erase(it);
|
|
341
|
+
auto key = it->first; // 应该报:访问失效迭代器
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
void trigger_bad_4(std::vector<int>& vec)
|
|
347
|
+
{
|
|
348
|
+
auto it = vec.begin();
|
|
349
|
+
vec.clear();
|
|
350
|
+
if (it != vec.end()) { // 应该报:clear后使用迭代器
|
|
351
|
+
// ...
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### 安全用例(不应该报)
|
|
357
|
+
|
|
358
|
+
```cpp
|
|
359
|
+
// test_BoundaryCondition_008_safe.cpp
|
|
360
|
+
void safe_good_1(std::vector<int>& vec)
|
|
361
|
+
{
|
|
362
|
+
for (auto it = vec.begin(); it != vec.end(); ) {
|
|
363
|
+
if (*it < 0) {
|
|
364
|
+
it = vec.erase(it); // 安全:使用返回值
|
|
365
|
+
} else {
|
|
366
|
+
++it;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
void safe_good_2(std::vector<int>& vec)
|
|
372
|
+
{
|
|
373
|
+
vec.erase(std::remove(vec.begin(), vec.end(), 0), vec.end()); // 安全:remove_if模式
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
void safe_good_3(std::set<int>& set)
|
|
377
|
+
{
|
|
378
|
+
for (auto it = set.begin(); it != set.end(); ) {
|
|
379
|
+
if (*it > 100) {
|
|
380
|
+
it = set.erase(it); // 安全:使用返回值
|
|
381
|
+
} else {
|
|
382
|
+
++it;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// NOPROTECT: 特殊处理场景
|
|
388
|
+
void noprotect_case(std::vector<int>& vec)
|
|
389
|
+
{
|
|
390
|
+
for (auto it = vec.begin(); it != vec.end(); ++it) {
|
|
391
|
+
vec.erase(it);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
```
|