我正在使用 std::list 的 remove() 來洗掉 for 回圈中的元素。但它正在造成分段錯誤。我沒有使用迭代器。程式如下。
#include <iostream>
#include <list>
using namespace std;
int main() {
list <int> li = {1, 2, 3, 4, 5};
for(auto x : li)
{
if (x == 4) {
li.remove(x);
}
}
return 0;
}
對于迭代器,我知道如果我們洗掉一個元素,迭代器就會失效,我們需要注意正確地遞增迭代器。但在這里我沒有使用迭代器,我使用的是不回傳任何內容的 remove()。如果我們不能在回圈中使用 remove 或者代碼是否有任何問題,任何人都可以告訴我。
uj5u.com熱心網友回復:
但在這里我沒有使用迭代器,我使用的是不回傳任何內容的 remove()。如果我們不能在回圈中使用 remove 或者代碼是否有任何問題,任何人都可以告訴我。
你誤會了。基于范圍的for回圈基于迭代器。所以在這個電話之后:
li.remove(x);
當前使用的迭代器變得無效。
例如,在 C 17 中,基于范圍的for回圈按以下方式定義(9.5.4 基于范圍的 for 陳述句):
1 基于范圍的for陳述句
for ( for-range-declaration : for-range-initializer ) statement相當于
{ auto &&__range = for-range-initializer ; auto __begin = begin-expr ; auto __end = end-expr ; for ( ; __begin != __end; __begin ) { for-range-declaration = *__begin; statement } }
注意這一點。使用基于范圍的for回圈來呼叫成員函式remove()沒有多大意義,因為該函式將洗掉所有具有給定值的元素。
如果編譯器支持 C 20,你可以寫:
std::erase( li, 4 );
uj5u.com熱心網友回復:
您可以使用erase-remove 習慣用法,而不是遍歷串列并洗掉元素,這會導致迭代器失效:
[演示]
#include <algorithm> // remove_if
#include <fmt/ranges.h>
#include <list>
int main() {
std::list<int> li = {1, 2, 3, 4, 5};
li.erase(
std::remove_if(std::begin(li), std::end(li), [](int i){ return i == 4; }),
std::end(li)
);
fmt::print("{}", li);
}
// Outputs:
//
// [1, 2, 3, 5]
uj5u.com熱心網友回復:
是的,您正在使用迭代器:基于范圍的for回圈使用迭代器。
請參閱https://en.cppreference.com/w/cpp/language/range-for的說明部分
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/495867.html
