Chỉnh sửa: Xin lỗi, phiên bản gốc của điều này là không chính xác. Đã sửa.
Đây là những gì đang diễn ra. đầu vào của bạn để remove_if
là:
1 2 3 4 5 6
^ ^
begin end
Và thuật toán remove_if
nhìn vào tất cả các số giữa begin
và end
(bao gồm begin
, nhưng không bao gồm end
), và loại bỏ tất cả các yếu tố giữa trận đấu mà vị ngữ của bạn. Vì vậy, sau remove_if
chạy, vector của bạn trông như thế này
1 2 3 ? 5 6
^^
begin new_end
đâu ?
là một giá trị mà tôi không nghĩ là xác định, mặc dù nếu nó đảm bảo được bất cứ điều gì nó sẽ là 4
. Và new_end
, trỏ đến kết thúc mới của chuỗi đầu vào bạn đã cung cấp cho nó, với các yếu tố phù hợp đã bị xóa, là số được trả lại bởi std::remove_if
. Lưu ý rằng std::remove_if
không chạm vào bất kỳ thứ gì ngoài chuỗi mà bạn đã cung cấp. Điều này có thể có ý nghĩa hơn với một ví dụ mở rộng hơn.
nói rằng đây là đầu vào của bạn:
1 2 3 4 5 6 7 8 9 10
^ ^
begin end
Sau std::remove_if
, bạn nhận được:
1 2 3 5 7 ? ? 8 9 10
^ ^
begin new_end
nghĩ về điều này trong một khoảnh khắc. Những gì nó đã làm là loại bỏ 4 và 6 từ sau đó, và sau đó thay đổi tất cả mọi thứ trong phần sau xuống để điền vào các phần tử đã xóa và sau đó di chuyển trình lặp end
đến đầu mới của cùng một chuỗi. Mục tiêu là để đáp ứng yêu cầu rằng trình tự (begin
, new_end
] mà nó tạo ra giống với chuỗi (begin
, end
] mà bạn đã chuyển vào, nhưng với một số thành phần nhất định bị xóa. Mọi thứ ở hoặc bên ngoài end
mà bạn đã chuyển được đụng đến nó.
gì bạn muốn để có được thoát khỏi, sau đó, là tất cả mọi thứ giữa iterator cuối đã được trả lại, và iterator cuối ban đầu mà bạn đã cho nó. Đây là những ?
"rác" giá trị. Vì vậy, cuộc gọi xóa của bạn thực sự phải là:
ints.erase(it, ints.begin()+4);
Cuộc gọi đến erase
mà bạn vừa xóa mọi thứ ngoài phần cuối của chuỗi mà bạn đã thực hiện việc xóa, đó không phải là những gì bạn muốn ở đây.
Điều phức tạp này là thuật toán remove_if
không thực sự gọi erase()
trên véc tơ, hoặc thay đổi kích thước của véc-tơ tại bất kỳ thời điểm nào. Nó chỉ thay đổi các phần tử xung quanh và để lại một số phần tử "rác" sau khi kết thúc chuỗi mà bạn yêu cầu nó xử lý. Điều này có vẻ ngớ ngẩn, nhưng toàn bộ lý do STL thực hiện theo cách này là tránh vấn đề với các trình vòng lặp không hợp lệ mà doublep đã đưa lên (và có thể chạy trên những thứ không phải là các container STL, như các mảng thô).
Đồ họa đẹp :) Vâng, tôi không nghĩ rằng nó là cần thiết để bỏ qua cuộc gọi erase(), nhưng trình gỡ lỗi cho tôi một số hành vi kỳ lạ sau remove_if(), vì vậy tôi đã tự hỏi nếu tôi đã làm điều gì đó sai hoặc loại sử dụng này không chính xác (sử dụng danh sách sau đó, như doublep đã nói) –
Rất tốt, phiên bản mở rộng của bạn thực sự xóa mọi thứ cho tôi. Tôi sẽ thử nghiệm các đề xuất của bạn và sớm đưa ra phản hồi –