2013-06-23 38 views
6

Tôi hỏi điều này bởi vì đó là một hạn chế làm suy yếu vì một số lý do rõ ràng nhưng tôi chắc chắn rằng những kẻ tiêu chuẩn C++ có lý do chính đáng để làm điều đó, và tôi muốn biết nó là gì. Không phải vì nó sẽ tạo ra bất kỳ sự khác biệt nào nhưng bởi vì nó sẽ làm cho tôi cảm thấy tốt hơn khi biết rằng có một lý do chính đáng cho nó.Tại sao con trỏ yếu không thể truy cập con trỏ cơ bản?

Đây là sự đảm nhận hiện tại của tôi; như tôi thấy con trỏ yếu có 2 cách sử dụng chính:

1) để tránh vòng lặp quyền sở hữu. 2) để giảm chi phí liên quan đến việc nảy xung quanh rất nhiều con trỏ được chia sẻ.

Cái cũ sẽ không được phục vụ và cái sau được phục vụ tốt hơn bằng cách thực hiện weak_ptr.get(), vậy tại sao nó không tồn tại? Thêm vào điểm, sẽ không weak_ptr.get() được hiệu quả hơn so với weak_ptr.lock(). Get(), hoặc có thể một trình biên dịch tối ưu hóa này là như nhau?

+2

Trong tài liệu hướng dẫn tăng, có giải thích tại sao 'weak_ptr' sẽ không trả về con trỏ thô bằng phương thức như' get() ': [Boost 1.43.0: weak_ptr] (http://www.boost.org /doc/libs/1_43_0/libs/smart_ptr/weak_ptr.htm). – Pixelchemist

+0

Sẽ đọc. Cảm ơn. – arman

Trả lời

9

Con trỏ yếu cần có khả năng kiểm tra xem con trỏ thông minh mà nó tham chiếu vẫn hợp lệ. Nếu nó không thể làm điều đó, sau đó bạn không thể biết liệu kết quả từ get là hợp lệ bởi thời gian bạn thực sự sử dụng nó.

Đó là lý do tại sao có lock; nó cung cấp cho bạn một con trỏ thông minh sẽ có hiệu lực cho tới chừng nào bạn cần nó (nó không phải là rất dài).

Nếu bạn muốn truy cập trực tiếp, thì những gì bạn thực sự muốn là một con trỏ "ngu ngốc" bình thường.

1

1) để tránh vòng lặp quyền sở hữu. 2) để giảm chi phí liên quan đến việc nảy xung quanh rất nhiều con trỏ được chia sẻ

Cái cũ sẽ không được phục vụ và cái sau được phục vụ tốt hơn bằng cách thực hiện weak_ptr.get(), vậy tại sao nó không tồn tại? Thêm vào điểm, sẽ không weak_ptr.get() được hiệu quả hơn so với weak_ptr.lock(). Get(), hoặc có thể một trình biên dịch tối ưu hóa này là như nhau?

Trước đây, đúng là con trỏ sai - yếu không phải là con trỏ chia sẻ chi phí kỳ diệu ... chúng khác nhau về mặt chức năng. Bạn cần phải chọn một trong đó phù hợp với tình hình của bạn.

Lý do chính để sử dụng con trỏ yếu là theo dõi một số dữ liệu mà bạn có thể muốn sử dụng nếu nó vẫn còn treo lơ lửng, nhưng có thể sống sót mà không có. Việc thiết lập điều đó liên quan đến điều kiện chủng tộc với người dùng các con trỏ chia sẻ, vì vậy trừ khi bạn có một số hiểu biết sâu sắc về tuổi thọ của đối tượng có nghĩa là bạn có thể chắc chắn mã của bạn có thể hoàn thành trước khi đối tượng bị phá hủy, con trỏ thô sẽ vô ích. Nếu bạn có cái nhìn sâu sắc bên trong thì bạn có thể có được một con trỏ thô ban đầu - thay vì của con trỏ yếu - nhưng thiết kế của con trỏ yếu được dự định để ngăn bạn vô tình nhận được một và tạo mã không an toàn. Thật vậy, bất kỳ cái nhìn sâu sắc như vậy có thể mong manh khi đối mặt với sự phát triển trung bình/dài hạn của mã, do đó, có lẽ tốt hơn không nên cố gắng thực hiện những tối ưu hóa như vậy trừ khi bạn hoàn toàn phải.

Có lẽ một ví dụ về việc sử dụng tốt của một con trỏ yếu sẽ giúp ...

Nói một đối tượng đại diện cho một cái gì đó trên màn hình - nếu bạn muốn nó để flash bạn thêm một con trỏ yếu vào một danh sách flasher timer-driven thì bạn có thể quên nó đi. Khi bộ đếm thời gian tiếp theo kích hoạt, nếu mã Flasher tìm thấy đối tượng bị phá hủy trước đó (tức là nó không còn trên màn hình nữa), flasher chỉ xóa nó khỏi danh sách, nhưng nó không muốn chia sẻ quyền sở hữu và giữ đối tượng xung quanh một cách không tự nhiên.Điều này có thể dễ dàng hơn là cố gắng để có mã theo dõi khi đối tượng biến mất khỏi màn hình phải xé nó ra khỏi danh sách flasher (và có khả năng chặn chờ đợi trên một khóa để làm như vậy).

+0

Điều đó giải thích lý do sử dụng 'weak_ptr', nhưng không phải lý do tại sao nó không có' get'. –

+0

@ChristianRau: đối với bất kỳ ai hiểu rằng 'get' nhận được một con trỏ thô, nó thực sự giải quyết (đoạn dài nhất ở trên). –

0

Điều này là do các nhà thiết kế của cặp shared_ptr/weak_ptr đã quyết định tốt hơn là chúng tôi không thể sử dụng nó không chính xác với chi phí tối ưu khi chúng tôi biết điều đó không quan trọng. Nó có thể không cần thiết để có chủ đề an toàn và ngữ nghĩa quyền sở hữu giống nhau - rất dễ dàng để tìm ra một khối mã duy nhất có một con trỏ thông minh đẹp, biết rằng giá trị rỗng của nó có ích nhưng chi phí khóa là trong khi không phải làm suy yếu, chắc chắn là một sự bi quan.

Cho dù shared_ptr/weak_ptr có cho phép điều này hay không (hoặc thêm notad_ptr trong đó notad - null khi hủy mục tiêu, nhưng không nhất thiết phải an toàn), hoặc đây là kiểu shared_ptr mới gây tranh cãi.

Chúng tôi giải quyết điều này trong cơ sở mã của chúng tôi bằng cách thêm một loại con trỏ thông minh mới, hỗ trợ các ngữ nghĩa đó. Tuy nhiên, điều này chắc chắn không phải là tối ưu vì có con trỏ thông minh không tuân thủ tiêu chuẩn chắc chắn là gây phiền nhiễu, nhưng ngữ nghĩa hữu ích bổ sung hơn là bù đắp cho thực tế chúng tôi có thể không thông minh [chơi chữ!] Như ủy ban tiêu chuẩn đầy đủ là:)

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