2012-01-25 31 views
8
Driver::~Driver() 
{ 
    AutoCritSec acsDriverList(m_csDriverList,true); 
    DRIVERLIST::iterator it = m_DriverList.begin(); 
    for(;it!=m_DriverList.end();it++) 
    { 
     if (it->second == this) 
     { 
      m_DriverList.erase(it); 
      it = m_DriverList.begin(); 
     } 
    } 
} 

Khi tôi biên dịch chương trình trong studio trực quan 2003, chương trình của tôi hoạt động tốt và tốt. nhưng khi tôi làm như vậy vào năm 2010, sau đó khi thoát khỏi chương trình tôi nhận được một số lỗi nhưmap/set iterator không gia tăng/set iterator không gia tăng

Expression:map/set iterator not incrementable 

và khi tôi bấm để bỏ qua điều này tôi nhận được

Expression:"standard c++ library out of range" && 0 

Có ai có bất kỳ ý tưởng là những gì đang diễn ra ở đây: Tôi sẽ vô cùng mắc nợ vì bất cứ lời đề nghị nào của bất cứ ai. Tấn cảm ơn và mong muốn ấm áp.

Trả lời

12

Nếu this là phần tử duy nhất trong danh sách, bạn sẽ vượt quá cuối danh sách.

Sau khi bạn xóa this khỏi danh sách, bạn đặt lại it = m_DriverList.begin();. Điều này là tốt. Sau đó, biểu thức vòng lặp được đánh giá (số i++ từ câu lệnh for), điều này gây ra it để được nâng cao khi kết thúc phạm vi.

Tiến hành trình lặp qua cuối vùng chứa khiến chương trình thể hiện hành vi không xác định. Các phiên bản gần đây của Visual C++ giúp phát hiện nhiều lỗi lặp phổ biến trong việc gỡ lỗi xây dựng chương trình của bạn và nâng cao các xác nhận để giúp bạn giải quyết chúng.

Bạn có thể giải quyết vấn đề bằng cách loại bỏ biểu hiện vòng lặp và di chuyển nó thành một tuyên bố else:

while (it != m_DriverList.end()) 
{ 
    if (it->second == this) 
    { 
     m_DriverList.erase(it); 
     it = m_DriverList.begin(); 
    } 
    else 
    { 
     ++it; 
    } 
} 

Mặc dù, khởi động lại lặp mỗi khi bạn xóa một phần tử là khá lãng phí. Xem xét thay vì sử dụng bằng cách sử dụng iterator được trả về bởi các cuộc gọi đến erase:

it = m_DriverList.erase(it); 
+0

Tốt giới thiệu của xóa/gỡ bỏ. Trong trường hợp cụ thể này m_DriverList dường như là một cặp chứa các cặp hoặc là một bản đồ của một số loại, kể từ khi thử nghiệm là trên nó-> thứ hai. Thay vì std :: remove nó sẽ yêu cầu std :: remove_if với hàm lambda hoặc so sánh. –

+0

Nếu vùng chứa là bản đồ (tiêu đề câu hỏi, quyền truy cập vào thành viên 'giây') thì tôi không nghĩ rằng thành ngữ * xóa-xóa * có thể được áp dụng. Thành ngữ giống với vòng lặp while mà bạn có, nhưng thay vì khởi động lại lần lặp, bạn sao chép và chuyển tiếp trình lặp và sau đó xóa vị trí hiện tại. –

+0

@ DavidRodríguez-dribeas @MarkTaylor: Tốt bắt; Tôi đã bị phân tâm bởi "Danh sách" trong tên biến. Trong C++ 11, 'erase' trả về bộ lặp (iterator) cho phần tử tiếp theo (hoặc đến một-past-the-end nếu không có phần tử tiếp theo), và Visual C++ 2010 hỗ trợ điều này. –

6

Các erase đúng ngữ cho container kết hợp như sau:

for (auto it = container.begin(); it != container.end() /* not hoisted */; /* no inc. */) 
{ 
    if (delete_condition) 
    { 
     container.erase(it++); 
    } 
    else 
    { 
     ++it; 
    } 
}