2012-03-06 42 views

Trả lời

16

Tiêu chuẩn không hoàn toàn đánh vần nó, nhưng v.erase(q) được xác định, "Xoá phần tử được trỏ đến bởi q" trong [sequence.reqmts]. Điều này có nghĩa là q phải thực sự trỏ đến một phần tử, mà trình lặp kết thúc không. Đi qua trong vòng lặp kết thúc là hành vi không xác định.

Thật không may, bạn cần phải viết:

auto it = std::find(...); 
if (it != <the part of ... that specifies the end of the range searched>) { 
    v.erase(it); 
} 

Tất nhiên, bạn có thể định nghĩa:

template typename<Sequence, Iterator> 
Iterator my_erase(Sequence &s, Iterator it) { 
    if (it == s.end()) return it; 
    return s.erase(it); 
} 

my_erase(v, std::find(v.begin(), v.end(), whatever)); 

c.erase() trên lợi nhuận chứa kết void, vì vậy để khái quát mẫu này để tất cả các container bạn cần một số hành động -> decltype.

+0

+1 để tham khảo chuẩn. –

+0

[docs] (http://www.cplusplus.com/reference/vector/vector/erase/) nói rằng "xoá các phần tử ở các vị trí khác với đầu cuối vector làm cho vùng chứa phải di chuyển ...". Dường như xuất hiện kết thúc() làm tham số. Và không nơi nào nói ngược lại một cách rõ ràng. Tôi không thích điều này ... – Pavel

+1

@Pavel: sau đó bạn sẽ phải đưa nó lên với các tác giả của "cplusplus.com". Nó là * không * tài liệu C++, tiêu chuẩn là tài liệu C++. Nhưng nó định nghĩa 'vị trí' là" Iterator trỏ đến một phần tử duy nhất ". Trình lặp kết thúc không trỏ đến một phần tử đơn lẻ. –

6

Bạn đã thử cách này chưa?

v.erase(remove_if(v.begin(), v.end(), (<your criteria>)), v.end()); 
+1

-1: Thuật toán không xóa các phần tử khỏi vùng chứa. –

+0

Thiếu các câu trả lời đúng khác không trả lời đúng. –

+4

Tôi không biết tại sao điều này đã được giảm giá (khác với câu trả lời ban đầu đã được chỉnh sửa). Các mã như nó là viết tắt là chính xác. –

23

Tẩy xoá end() (hoặc cho rằng vấn đề, thậm chí nhìn vào mục tiêu của end()) là hành vi không xác định. Hành vi không xác định được phép có bất kỳ hành vi nào, bao gồm "chỉ hoạt động" trên nền tảng của bạn. Điều đó không có nghĩa là bạn nên làm điều đó; nó vẫn chưa được xác định hành vi, và tôi sẽ cắn bạn theo những cách tồi tệ nhất khi bạn ít mong đợi nó sau này.

Tùy thuộc vào những gì bạn đang làm, bạn có thể muốn xem xét set hoặc unordered_set thay vì vector tại đây.

+0

cảm ơn, tôi biết UB là gì, tôi chỉ muốn biết, là nó thực sự UB. – RiaD

+0

@RiaD: Có, đó là UB. Tuy nhiên, giải pháp rất đơn giản, chỉ cần kiểm tra trước khi bạn xóa: '{auto it = v.find (x); if (it! = x.end()) {v.erase (nó); }} ' –

+0

Câu hỏi dành cho bạn @Billy. Trong sự tò mò, không kết thúc() - 1 công việc? Điều này khác với pop_back() như thế nào? – Gaffi