2017-11-14 42 views
8

Tôi có ứng dụng đa luồng và tài nguyên được chia sẻ std::map<KeyType, ElementType>. Tôi sử dụng một mutex để bảo vệ chèn, lấy và loại bỏ.Có thể tham chiếu đến phần tử bên trong std :: map bị vô hiệu không?

Phương thức nhận của tôi trả về tham chiếu đến phần tử được lưu trữ (mở khóa khi trả về), sau đó tôi thực hiện một số thao tác với phần tử đó.

Câu hỏi: Có thể rằng khi làm việc với các tài liệu tham khảo yếu tố lưu trữ, thread khác có thể thay đổi std::map nên nguyên tố này sẽ được chuyển đến một địa chỉ khác nhau và các tài liệu tham khảo sẽ không còn giá trị? (Tôi biết có một số triển khai ADT nhất định làm sắp xếp lại ADT về thay đổi kích thước).

+0

Bạn chặn phương pháp của mình ở đâu? bên trong, hoặc gói chúng với mutex? –

+4

Khác với việc xóa phần tử bạn làm việc, nó không thể làm mất hiệu lực. – StoryTeller

+0

Điều này cũng không phải là vấn đề trong môi trường đa luồng không? Ví dụ. bạn lấy một tham chiếu từ bản đồ của bạn và lưu trữ nó ở đâu đó, sau đó nếu bạn thay đổi bản đồ, tham chiếu được lưu trữ trước đó cũng có thể bị vô hiệu. –

Trả lời

7

Nguyên tắc iterator huỷ bỏ hiệu lực đối với container kết hợp (mà std::map là) nói tại [associative.reqmts]/9:

Các chèn và đặt vào một chỗ các thành viên sẽ không ảnh hưởng đến hiệu lực của lặp và tài liệu tham khảo để các thùng chứa, và các thành viên xóa thì tùy theo tính chỉ vô hiệu hóa các trình vòng lặp và tham chiếu đến các phần tử đã xóa.

Vì vậy, nếu một chuỗi chèn phần tử, nó sẽ không ảnh hưởng đến bất kỳ tham chiếu nào đến các phần tử hiện có. Nhưng nếu nó loại bỏ một cái gì đó, các chủ đề khác có thể được borked. Một số hình thức của khóa yếu tố khôn ngoan là theo thứ tự, tôi muốn nói.

+1

"các chủ đề khác có thể được borked" - nhưng chỉ khi họ đang sử dụng các phần tử bị xóa. Cấu trúc chương trình có thể là như vậy mà điều này không thể xảy ra. (Thay đổi thành 'std :: map >' có thể là sự thay đổi đơn giản nhất. Nó cho phép thư viện chuẩn thực hiện tất cả việc nâng cao việc duy trì số tham chiếu.) –

+0

Có thể đáng chú ý, rằng điều này đảm bảo không * không * áp dụng cho 'std :: unordered_map', do đó," tối ưu hóa "bằng cách chuyển sang đó sẽ không phải là một động thái tốt. –

3

Chủ đề khác có thể xóa phần tử hoặc hủy bản đồ, tất nhiên cũng sẽ làm mất hiệu lực phần tử.

Việc xóa một phần tử chỉ làm mất hiệu lực các trình vòng lặp và các lần nhập lại thành phần tử này. Chèn không làm mất hiệu lực vòng lặp hoặc tham chiếu vào bản đồ.

(đó là những gì các second-hand documentation says, ít nhất - và đó là một giả định tôi giữ mà không bao giờ được hết hiệu lực, nếu bằng chứng đếm.)

Một vấn đề khác vẫn là: Thao tác của nguyên tố này thông qua các tài liệu tham khảo trở lại không phải là thread an toàn . Bạn cần đồng bộ hóa, ví dụ: cho mỗi phần tử - và đảm bảo bạn không vi phạm phân cấp khóa.

+0

[N4296] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers /2014/n4296.pdf) (bản nháp comittee mới nhất trước C++ 14) cho biết điều tương tự tại §23.2.4 para 9 (chân trang 763). –

Các vấn đề liên quan