2010-09-25 17 views
14

Ai đó có thể giúp tôi ở đây không?Xóa-xóa thành ngữ với tiêu chuẩn :: đặt lỗi với lỗi liên quan đến constness

Biên dịch mã này:

void test() 
{ 
    std::set<int> test; 
    test.insert(42); 
    test.erase(std::remove(test.begin(), test.end(), 30), test.end()); // <- Line 33 
} 

Là tạo ra được lỗi sau khi biên dịch:

$ make 
g++ -c -Wall -pedantic-errors -Wextra -Wunused -Werror a_star.cpp 
/usr/lib/gcc/i686-pc-cygwin/4.3.4/include/c++/bits/stl_algo.h: In function `_FIter std::remove(_FIter, _FIter, const _Tp&) [with _FIter = std::_Rb_tree_const_iterator<int>, _Tp = int]': 
a_star.cpp:33: instantiated from here 
/usr/lib/gcc/i686-pc-cygwin/4.3.4/include/c++/bits/stl_algo.h:779: error: assignment of read-only location `__result.std::_Rb_tree_const_iterator<_Tp>::operator* [with _Tp = int]()' 
make: *** [a_star.o] Error 1 

Trả lời

22

Trong std::set, các yếu tố không thể sửa đổi được. Vì vậy, std::set::iterator cũng không thể sửa đổi. Từ this hướng dẫn, phần 27.3.2.1:

Trong container kết hợp đơn giản, nơi các yếu tố là chìa khóa, các yếu tố này là hoàn toàn không thay đổi; do đó, trình lặp loại lồng nhau và const_iterator là như nhau.

Do đó, không thể áp dụng thành ngữ erase-remove. Bạn phải viết một vòng lặp for và sử dụng hàm thành viên std::set::erase bên trong nó. Xem question này và điều này được chấp nhận answeranswer khác để biết chi tiết chính xác, nhưng trong ngắn hạn, các vòng lặp là như sau

typename std::set::iterator set_iter; 

for(set_iter it = s.begin(); it != s.end(); /* blank */) { 
    if(some_condition()) { 
     s.erase(it++);  // Note the subtlety here 
    } 
    else { 
     ++it; 
    } 
} 
0

Nếu tôi nhớ tốt, std :: remove là không bao giờ được sử dụng với một std :: set thành phần.

Vì một bộ không phải là mảng thuần túy, bạn phải sử dụng xóa.

5

Erase-remove thành ngữ không thể được sử dụng với container kết hợp. Các thùng chứa liên kết không cho phép sửa đổi toàn bộ phần tử vùng chứa thông qua trình lặp, tức là các hoạt động chuỗi đột biến (như std::remove) không thể được áp dụng cho chúng.

1

Như đã nói mã của bạn không hoạt động vì bạn cố gắng sửa đổi một chuỗi bên trong một vùng chứa liên kết, nhưng bạn không thể làm điều này bởi vì chuỗi này là không thay đổi. Lý do: tập hợp giữ một chuỗi được sắp xếp, thường là trong một cây nhị phân. Nếu bạn được phép sửa đổi nó, bạn có thể làm hỏng thùng chứa và chương trình sẽ bị lỗi. Btw, nó vẫn có thể xảy ra trong một số tình huống.

Bạn có thể thay đổi mã của bạn như thế này:

test.erase(30); 

Hoặc sử dụng (1) mã ArunSaha cho tiêu chí phức tạp hơn.